9

我最近一直在使用嵌套集模型中的废话。我喜欢为几乎所有有用的操作和视图设计查询。我坚持的一件事是如何选择节点的直接子代(并且只有子代,而不是进一步的后代!)。

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

4

6 回答 6

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”,因此我可以轻松地询问节点的子节点。

于 2009-03-18T18:39:53.367 回答
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

也就是说,“从相关节点的所有后代中,选择它们与节点之间没有祖先的节点”。

于 2009-03-19T09:40:00.007 回答
6

这个更好更小

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

下面的两个查询假定您的表已命名tree,您的左列已命名lft,右列已命名rgt,并且您的主键已命名id。更改这些值以满足您的需要。此外,检查第一个 select 语句。您会看到我正在查找节点 5 的直接后代。更改数字 5 以查找您想要的任何节点的子节点。

我个人认为这是一个比迄今为止提出的其他查询更时尚、更性感、更有效的查询。

SELECT `lft`, `rgt` INTO @parent_left, @parent_right FROM efm_files WHERE `id` = 5;
SELECT `child`.`id`
FROM `tree` AS `child`
LEFT JOIN `tree` 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`.`id` IS NULL
于 2010-01-15T15:51:35.233 回答
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

于 2011-02-01T03:33:01.910 回答
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

维基百科

于 2011-11-09T07:54:36.653 回答
0

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

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

于 2014-09-01T01:41:30.730 回答