【问题标题】:MySQL Nested Sets - How to find parent of node?MySQL嵌套集 - 如何找到节点的父节点?
【发布时间】:2010-12-08 19:42:21
【问题描述】:

我有您运行的嵌套集层次结构类型设置,其中包含以下列:

表名:

myset

列:

id, name, lft, rgt

有没有人知道一个查询来确定节点的父节点

我读了几个地方,在你的表中也有一个 parent_id 列来跟踪这一点很方便,但这似乎是多余的,而且它似乎可能与嵌套的不同步如果在添加/删除/移动集合中的任何内容时错误地执行了查询,则设置。

【问题讨论】:

    标签: sql mysql hierarchy nested-sets


    【解决方案1】:

    看看this question。它与您的相似。我已经在那里发布了您可能需要的查询。

    SELECT title, (SELECT TOP 1 title 
               FROM tree t2 
               WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt    
               ORDER BY t2.rgt-t1.rgt ASC) AS parent
    FROM tree t1
    ORDER BY rgt-lft DESC
    

    希望有你需要的。

    对于下表:

    +-------------+----------------------+-----+-----+
    | category_id | name                 | lft | rgt |
    +-------------+----------------------+-----+-----+
    |           1 | ELECTRONICS          |   1 |  20 |
    |           2 | TELEVISIONS          |   2 |   9 |
    |           3 | TUBE                 |   3 |   4 |
    |           4 | LCD                  |   5 |   6 |
    |           5 | PLASMA               |   7 |   8 |
    |           6 | PORTABLE ELECTRONICS |  10 |  19 |
    |           7 | MP3 PLAYERS          |  11 |  14 |
    |           8 | FLASH                |  12 |  13 |
    |           9 | CD PLAYERS           |  15 |  16 |
    |          10 | 2 WAY RADIOS         |  17 |  18 |
    

    它产生输出:

    title                | parent
    ----------------------------------------------
    ELECTRONICS          | NULL
    PORTABLE ELECTRONICS | ELECTRONICS
    TELEVISIONS          | ELECTRONICS
    MP3 PLAYERS          | PORTABLE ELECTRONICS
    FLASH                | MP3 PLAYERS
    CD PLAYERS           | PORTABLE ELECTRONICS
    2 WAY RADIOS         | PORTABLE ELECTRONICS
    TUBE                 | TELEVISIONS
    LCD                  | TELEVISIONS
    PLASMA               | TELEVISIONS
    

    【讨论】:

    • 你知道为什么ORDER BY t2.rgt-t1.rgt会在sqlite中返回错误吗? SQLSTATE[HY000]: General error: 1 no such column: t1.rgt ...当我从 order by 中删除 t1.rgt 时它可以工作,所以它似乎是 order by ...的问题。
    【解决方案2】:

    TOP 是一个 MSSQL 命令,对 MySQL 使用 LIMIT:

    SELECT title, (SELECT title 
           FROM tree t2 
           WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt    
           ORDER BY t2.rgt-t1.rgt ASC
           LIMIT 1) 
    AS parent FROM tree t1 
    ORDER BY (rgt-lft) DESC
    

    应该做的伎俩..

    【讨论】:

      【解决方案3】:

      只是为了补充这些对我有很大帮助的答案,

      在某些情况下,我需要找到节点的直接父节点,以及节点链的最顶层父节点,

      我使用以下内容作为基础以从子到父的顺序获取项目

      SELECT parent.*  FROM
              nested_set node,
              nested_set parent
              WHERE (
                  node.set_left BETWEEN parent.set_left AND parent.set_right          
              )
              AND node.set_id={CHILD_NODE_ID_HERE}
              ORDER BY parent.set_right - parent.set_left
              #LIMIT 1,1
      

      然后添加LIMIT 1,1 以仅捕获作为直接父级的第二行

      还应该注意,如果节点本身是最顶层的父节点,那么它不会有 直接父节点,因此对于上述查询,它应该返回一个 LIMIT 1,1空结果集

      为了获得最顶层的父节点,我颠倒了 order by 子句,包括检查节点本身是否是顶层父节点,并将结果限制在第一行

      SELECT parent.* AS top_level_right FROM
              nested_set node,
              nested_set parent
              WHERE (
                  node.set_left >= parent.set_left 
                  AND node.set_left <= parent.set_right
              )
              AND node.set_id={CHILD_NODE_ID_HERE}
              ORDER BY parent.set_left - parent.set_right
              LIMIT 1
      

      在最后一个查询中,我使用了&gt;= &lt;= 运算符,以便所选范围包含子节点(如果它也恰好是顶级父节点)

      【讨论】:

      • 为什么使用order by parent.set_left - parent.set_right ASC 而不是order by parent.lft desc?您的方法正在寻找最小的差距,我的只是使用更快的方法获取直接父级。
      【解决方案4】:

      我对 Lucasz 的查询有疑问。我的 mysql 版本不理解 TOP 命令。我不得不改用 LIMIT 。这是修改后的代码。

      SELECT 
         `id`, 
         (SELECT 
            `id`
          FROM 
             `[*** YOUR TABLE ***]` AS `t2` 
          WHERE 
             `t2`.`left_id`  < `t1`.`left_id`AND 
             `t2`.`right_id` > `t1`.`right_id`
          ORDER BY 
             `t2`.`right_id`-`t1`.`right_id`ASC 
          LIMIT 
             1) AS `parent`
      FROM 
          `[*** YOUR TABLE ***]` AS `t1`
      WHERE 
          `t1`.`id` = [*** ID OF THE NODE WHOS PARENT YOU WISH TO LOOKUP ***]
      ORDER BY 
          `right_id`-`left_id` DESC
      

      显然,更改 [ ] 中的内容以满足您的需要。同时删除 [ ] 的。此查询仅返回 ONE 行。就这样……

      id  parent
      7   3
      

      【讨论】:

        【解决方案5】:
        select * from myset
          where lft < :lftOfCurrent and rgt > :lftOfCurrent
          order lft desc
          limit 1
        

        您可以使用最大值而不是订单/限制,并且您可能需要另一个关键字来将结果限制为一行,具体取决于您的数据库。如果您的数据库返回独占集,那么介于而不是 将起作用,而 MySQL 不会。

        【讨论】:

          【解决方案6】:
          SELECT parent.name 
          FROM myset AS node, myset AS parent 
          WHERE parent.lft < node.lft 
          AND parent.rgt > node.rgt 
          AND node.id = {YOUR CATEGORY ID} 
          ORDER BY ( parent.rgt - parent.lft ) ASC LIMIT 1;
          

          【讨论】:

            【解决方案7】:

            所有的祖先都是由

            SELECT id FROM thetable
            WHERE x BETWEEN lft and rgt;
            

            所以,直接父母是lft和rgt之间差异最小的祖先。

            SELECT id FROM thetable
            WHERE x BETWEEN lft and rgt
            ORDER BY (rgt-lft)
            LIMIT 1
            

            【讨论】:

            • 如果你的 x 应该是元素的 id,那么你的陈述是错误的。
            【解决方案8】:

            spankmaster79 的代码并非完全错误。我修改了他的代码,它成功了。

            SELECT parent . * FROM Nested_Category AS node, Nested_Category AS parent 
            enter code hereWHERE node.leftSide
            BETWEEN parent.leftSide
            AND parent.rightSide
            AND node.id ='Enter the Node ID'
            ORDER BY (
            parent.rightSide - parent.leftSide
            )
            LIMIT 1 , 1
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-10-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-21
              • 1970-01-01
              • 1970-01-01
              • 2020-02-27
              相关资源
              最近更新 更多