如何有效地检索树中节点的路径(与帖子“将平面表解析为树?”相关)

Posted

技术标签:

【中文标题】如何有效地检索树中节点的路径(与帖子“将平面表解析为树?”相关)【英文标题】:How to retrieve the path to a node in a tree - efficiently (related to the post 'parse a flat table into a tree?') 【发布时间】:2009-08-17 19:37:10 【问题描述】:

这个问题是这个帖子的后续问题:

What is the most efficient/elegant way to parse a flat table into a tree?

我喜欢 ClosureMap 解决方案,但我还有一个问题要解决。

如何轻松检索树中特定节点的路径?例如,如果您查看提供的树:

ID 节点名称

1 '节点 1' 2 '节点 1.1' 3 '节点 2' 4 '节点 1.1.1' 5 '节点 2.1' 6 '节点 1.2'

1.1.1 的路径是:

ID = 1、2、4

不进行递归 SQL 调用,是否有一种优雅的方式来检索路径?

【问题讨论】:

【参考方案1】:
SELECT ancestor_id
FROM ClosureTable
WHERE descendant_id = 4;

返回值 1、2、4。但它们在不同的行中返回,并且它们没有表明它们的顺序正确(我们可能不假设数字顺序对应于树的层次结构顺序)。

有时您还会将每个路径的深度存储在ClosureTable 中。但即使没有,您也可以计算给定节点有多少祖先,并使用它进行排序:

SELECT ct1.ancestor_id, COUNT(*) AS depth
FROM ClosureTable ct1
 JOIN ClosureTable ct2 ON (ct1.ancestor_id = ct2.descendant_id)
WHERE ct1.descendant_id = 4
GROUP BY ct1.ancestor_id
ORDER BY depth;

是的,这仍然会以三行形式返回结果。如果你使用 mysql,你可以访问GROUP_CONCAT()。否则很容易获取三行并将它们的值连接到应用程序代码中。

【讨论】:

谢谢...我应该更多地分析您的解决方案,这是有道理的。 要获取订单,我想您可以使用附加的“path_length”字段按子级向父级检索:SELECT original_id FROM ClosureTable WHERE descendant_id = 4 ORDER BY path_length DESC;【参考方案2】:

我想我找到了最好的解决方案,但并没有真正意识到它在我提到的帖子中:)。

Site Point 有一篇很好的文章,展示了如何使用 Left/Right 属性检索特定节点:

http://www.sitepoint.com/article/hierarchical-data-database/2/

【讨论】:

见上文。我更喜欢 Bill 的解决方案,而不是必须管理每个节点的左/右属性。 左/右解决方案称为“嵌套集”。它对查询很有效,但是当您需要更改树时就很麻烦了。

以上是关于如何有效地检索树中节点的路径(与帖子“将平面表解析为树?”相关)的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 实时数据库能否有效地循环浏览数十亿条帖子并由发布它们的用户检索?

数据结构与算法之深入解析“二叉树中的最长交错路径”的求解思路与算法示例

c语言中如何获取树中所有叶子节点的路径

如何在解析树中查找节点的路径

如何有效地合并两个 BST?

C/C++:如何将数据存储在 B 树中的文件中