【问题标题】:Select ancestors and immediate children of a node in a nested set tree using MYSQL使用 MYSQL 在嵌套集合树中选择节点的祖先和直接子节点
【发布时间】:2010-02-11 23:45:58
【问题描述】:

希望你们中的一些mysql专家可以帮助我。

我有存储在嵌套集中的搜索标签数据。

TABLE searchTags

searchTagID
searchTag
lft
rgt

(我使用嵌套集是因为有时我需要轻松选择树的整个分支。)

我想构建一个查询,该查询将返回与 LIKE 匹配的节点的结果集、每个节点的祖先以及每个节点的直接子节点。

例如,如果这是我的嵌套集...

                          1_tagA_22
     2_tagB1_11          12_tagB2_13           14_tagB3_21
3_taC1_4   5_taC2_10                                   15_tagC3_20
               6_tagD1_9                        16_tagD2_17    18_tagD3_19
                  7_tagE1_8

...对于我的搜索针,我有 LIKE CONCAT('%','tagc','%'),我想返回如下所示的内容:

searchTag   |   ancestors   |  immediateChildren
tagC1          tagB1,tagA       NULL
tagC2         tagB1,tagA       tagD1
tagC3          tagB3,tagA       tagD2,tagD3

我目前正在处理多个查询。首先,我选择搜索标签及其祖先的结果集。然后我遍历这个结果集,对于每个结果,我做另一个选择来获得直接的孩子。 (我将这些查询包括在下面,以供参考。)

这种方法有效,但我觉得这是一种效率低下的解决方案,迟早会爆炸。 :) 我想知道是否有更好的方法来做到这一点 - 即有没有办法将所有这些组合成一个更有效的 SELECT 语句?

任何建议将不胜感激。

谢谢!

参考: 我使用以下选择搜索标签和祖先的路径...

    SELECT 

        node.searchTag, 

        GROUP_CONCAT(parent.searchTag 
        ORDER BY parent.lft DESC
        SEPARATOR '; ') AS ancestors 


    FROM 

        searchTags AS node,
        searchTags AS parent

    WHERE node.lft BETWEEN parent.lft AND parent.rgt
    AND parent.lft < node.lft
    AND node.searchTag LIKE CONCAT('%','tagc','%')
    GROUP BY node.searchTagID;

...然后我遍历这个结果集并为每个结果运行另一个查询以获取直接子级(使用 mrbinky3000 的出色方法):

SELECT lft, rgt INTO @parent_left, @parent_right FROM searchTags WHERE searchTagID = $id;

SELECT 

    GROUP_CONCAT(child.searchTag SEPARATOR "; ") as searchTag

FROM searchTags AS child
LEFT JOIN searchTags AS ancestor ON
    ancestor.lft BETWEEN @parent_left+1 AND @parent_right-1 AND
    child.lft BETWEEN ancestor.lft+1 AND ancestor.rgt-1
WHERE
    child.lft BETWEEN @parent_left+1 AND @parent_right-1 AND
    ancestor.searchTagID IS NULL;

【问题讨论】:

    标签: mysql nested-sets sql


    【解决方案1】:

    Here 是一个带有解决方案的 SQL Fiddle。

    SQL 是:

    SELECT t0.title node
          ,GROUP_CONCAT(t5.title) children
          ,(SELECT GROUP_CONCAT(t6.title)
                        FROM Tree t6
                        WHERE t6.lft<t0.lft AND t6.rgt>t0.rgt
                        ORDER BY t6.lft) ancestors
    FROM Tree t0
         LEFT JOIN
         (SELECT *
          FROM (SELECT t1.lft node
                      ,MAX(t2.lft) nodeparent
                FROM Tree t1
                     INNER JOIN
                     Tree t2 ON t1.lft>t2.lft AND t1.rgt<t2.rgt
                GROUP BY t1.lft) t3 
                LEFT JOIN
                Tree t4 ON t3.node=t4.lft) t5 ON t0.lft=t5.nodeparent
    GROUP BY t0.title;
    

    祖先是 select 语句中的一个非常简单的子查询。

    对于孩子,子查询 t3 通过查找具有 MAX(lft) 的每个节点的祖先来创建一个邻接列表,然后将其连接到 t4 以获得孩子的名字。

    随意将您喜欢的任何WHERE 子句放在底部。

    【讨论】:

      【解决方案2】:

      阅读这些关于 MySQL 中嵌套集的好文章 http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/>http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-26
        相关资源
        最近更新 更多