有一种简单的方法来查询节点的子节点吗?

时间:2009-03-18 18:18:00

标签: sql tree nested-set-model

我最近一直在使用Nested Set Model的废话。我很高兴为几乎所有有用的操作和视图设计查询。我坚持的一件事是如何选择一个节点的直接孩子(和孩子,而不是其他后代!)。

说实话,我确实知道一种方法 - 但它涉及到无法管理的SQL数量。我确信有一个更简单的解决方案。

6 个答案:

答案 0 :(得分:9)

您是否阅读过您发布的文章?它位于“查找节点的直接下属”标题下

SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
FROM nested_category AS node,
    nested_category AS parent,
    nested_category AS sub_parent,
    (
        SELECT node.name, (COUNT(parent.name) - 1) AS depth
        FROM nested_category AS node,
        nested_category AS parent
        WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.name = 'PORTABLE ELECTRONICS'
        GROUP BY node.name
        ORDER BY node.lft
    )AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
    AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
    AND sub_parent.name = sub_tree.name
GROUP BY node.name
HAVING depth <= 1
ORDER BY node.lft;

然而,我所做的(这是作弊)是我将嵌套集合与邻接列表相结合 - 我在表格中嵌入了“parent_id”,因此我可以轻松地请求节点的子节点。

答案 1 :(得分:7)

在我看来,如果没有子查询或父列冗余,这应该很容易实现!例如,父母的左边和右边已知:

SELECT child.id
FROM nodes AS child
LEFT JOIN nodes AS ancestor ON
    ancestor.left BETWEEN @parentleft+1 AND @parentright-1 AND
    child.left BETWEEN ancestor.left+1 AND ancestor.right-1
WHERE
    child.left BETWEEN @parentleft+1 AND @parentright-1 AND
    ancestor.id IS NULL

也就是说,“从所讨论的节点的所有后代中挑选出自己与节点之间没有祖先的那些”。

答案 2 :(得分:5)

这一个更好更小

用户“bobince”几乎拥有它。我想出来并让它为我工作,因为我有比大多数人更多的MySQL经验。但是,我可以看出为什么鲍比斯的回答可能会吓跑人们。他的询问不完整。您需要先将parent_left和parent_right选择为mysql变量。

下面的两个查询假设您的表名为tree,左侧列名为lft,右列名为rgt,主键名为{{1} }}。更改这些值以满足您的需求。另外,检查第一个select语句。您将看到我正在查找节点5的直接后代。更改数字5以查找您想要的任何节点的子节点。

我个人认为这是一个比目前为止提供的其他人更时尚,更性感,更有效的查询。

id

答案 3 :(得分:0)

我知道我正在做一个死灵帖子, 但这是我的意见。

为什么不在嵌套集中包含“深度”列? 深度列将指示项目的“级别”。

因此,要选择项目的直接孩子,只需执行

select c.*
from tree as p
join tree as c on (c.left > p.left and c.right < p.right and c.depth = p.dept + 1) where p.id = @parentID

答案 4 :(得分:0)

我也会选择深度专栏。但是使用

SELECT Child.Node, Child.LEFT, Child.RIGHT
FROM Tree AS Child, Tree AS Parent
WHERE
        Child.Depth = Parent.Depth + 1
        AND Child.LEFT > Parent.LEFT
        AND Child.RIGHT < Parent.RIGHT
        AND Parent.LEFT = 1  -- Given Parent Node Left Index

Wikipedia

答案 5 :(得分:0)

我发现Wikipedia link具有良好的最小化答案版本以及选定的答案。

SELECT DISTINCT Child.Name
FROM ModelTable AS Child, ModelTable AS Parent 
WHERE Parent.Lft < Child.Lft AND Parent.Rgt > Child.Rgt  -- associate Child Nodes with ancestors
GROUP BY Child.Name
HAVING MAX(Parent.Lft) = @parentId  -- Subset for those with the given Parent Node as the nearest ancestor

并且,你们中的任何人都试图用Linq表达它,请点击链接:https://stackoverflow.com/a/25594386/361100