【发布时间】:2013-01-31 19:30:30
【问题描述】:
根据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
我认为 3 个 SELECT 的 SQL 非常糟糕——但它确实让我得到了 lft 和 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;
这对我来说似乎很讨厌 - 七个 SELECTs !
这可以优雅地完成吗(最好在一个查询中,但没那么重要 - 可读性 > 单个查询)?
顺便说一句 - lft 和 rgt 是我的 MPTT 编号字段名称
编辑 ::: 实验后我意识到我笨拙的 SQL 并没有做我想要的。它仅适用于比根深 > 2 层的节点。
我的问题是:参考帖子顶部链接的图表 - 如果用户“选择”子树的任何叶子或父节点,我需要获取整个子树,不包括根。
因此,如果用户选择“Cherry”、“Banana”、“Red”、“Yellow”或“Fruit”,我需要整个“Fruit”子树。
【问题讨论】:
标签: mysql sql tree binary-tree tree-traversal