MySQL修改了预订树遍历 - 根据节点获取子树

时间:2013-01-31 19:30:31

标签: mysql sql tree binary-tree tree-traversal

根据picture here on sitepont我有一个标准的mptt树表。我不能为我的生活找到一个很好的方法来获得基于所选节点的整个子树。

示例(来自该链接页面):想象一下,如果有人选择“Cherry”,树就是一个菜单 - 我希望从“Fruit”节点向下获取所有项目。

所以,我可以使用

获得最终的父行(不包括我不想要的根)
SELECT lft, rgt FROM menu_items
WHERE lft < (SELECT lft FROM menu_items WHERE id = 'Cherry') 
AND rgt > (SELECT rgt FROM menu_items WHERE id = 'Cherry') 
AND lft > 1
ORDER BY lft ASC LIMIT 1

我认为这是一个非常糟糕的SQL与3选择 - 但它确实让我lft&amp;我可以在进一步查询中使用rgt来获取lft和rgt之间的所有节点 - 从而获得“Cherry”所在的子树。

我用它作为在一个查询中完成所有操作的基础 - 这导致了这种可憎的行为:

SELECT * FROM menu_items 
WHERE lft BETWEEN 
    (SELECT lft FROM  menu_items
    WHERE lft < (SELECT lft FROM menu_items WHERE id = 'Cherry') 
    AND rgt > (SELECT rgt FROM menu_items WHERE id = 'Cherry') 
    AND lft > 1
    ORDER BY lft ASC LIMIT 1)
AND 
    (SELECT rgt FROM  menu_items
    WHERE lft < (SELECT lft FROM menu_items WHERE id = 'Cherry') 
    AND rgt > (SELECT rgt FROM menu_items WHERE id = 'Cherry') 
    AND lft > 1
    ORDER BY lft ASC LIMIT 1)
ORDER BY lft ASC;

这对我来说似乎很讨厌 - 七个SELECT!

这可以优雅地完成(最好是在一个查询中,但无关紧要 - 可读性&gt;单个查询)?

BTW - lft和rgt是MPTT编号的字段名称

编辑:::经过实验,我意识到我的笨拙SQL不能做我想做的事。它仅适用于节点&gt;比根深2级。

我的问题是:参考帖子顶部链接的图表 - 如果用户“选择”任何叶子或子树的父节点,我需要获得整个子树,不包括root。

因此,如果用户选择“Cherry”,“Banana”,“Red”,“Yellow”或“Fruit”,我需要整个“Fruit”子树。

2 个答案:

答案 0 :(得分:1)

尝试以下查询:

SELECT menu_items.* FROM menu_items ,
(SELECT lft as lft_inner,rgt as rgt_inner FROM menu_items WHERE id = 'Cherry')  
as menu_innner 
WHERE lft < lft_inner  
AND rgt > rgt_inner
AND lft > 1
ORDER BY lft ASC

答案 1 :(得分:0)

------------------------------------------------------------------
SELECT yourtable.* FROM yourtable ,
(SELECT lft as lft_inner,rgt as rgt_inner FROM yourtable WHERE id=178)  
as menu_innner 
WHERE lft > lft_inner  
AND rgt < rgt_inner
AND lft > 1
ORDER BY lft ASC
-----------------------------------------------------------------------