从使用物化路径编码树的表中选择,按深度优先排序(无递归/ltree)

Posted

技术标签:

【中文标题】从使用物化路径编码树的表中选择,按深度优先排序(无递归/ltree)【英文标题】:Select from a table that uses materialized path to encode a tree, ordered by depth-first (no recursive/ltree) 【发布时间】:2012-02-24 04:57:14 【问题描述】:

我在关系数据库中有一个表,我在其中使用称为 Materialized path(也称为 Lineage 列)的技术对树进行编码。也就是说,对于树中的每个节点,我在表中都有一行,对于每一行,我都有一个名为 ancestry 的字符串列,我在其中存储从根节点到该行表示的节点的路径。

是否可能,如果是 - 如何选择表中按 preorder 排序的行,即它们应该按照访问树的顺序出现在结果集中depth-first。我使用 mysql - 所以没有递归查询和 ltree 扩展

例如,一棵树,它是表,并按预排序选择:

 1        SELECT * FROM nodes   SELECT * FROM nodes ORDER BY ?depth_first_visit_order?
| \       id | ancestry         id | ancestry
2   3     -------------         -------------
|  | \    1  | NULL             1  | NULL           NOTE: I don't care about the
4  5  6   2  | 1                2  | 1                    order of siblings!
   |      3  | 1                4  | 1/2
   7      4  | 1/2              3  | 1
          5  | 1/3              5  | 1/3
          6  | 1/3              7  | 1/3/5
          7  | 1/3/5            6  | 1/3

注意:我对通过物化路径编码执行此操作非常感兴趣! 相关:What are the options for storing hierarchical data in a relational database?

【问题讨论】:

类似***.com/questions/2797720/… 【参考方案1】:

我相信你想要的是字母排序。

SELECT id, ancestry, ancestry + '/' + CAST(id as nvarchar(10)) AS PathEnumeration
FROM nodes
ORDER BY 3 ASC;

我真的不记得 MySQL 是如何连接的,但我确信我的意思很清楚。

1
1/2
1/2/4
1/3
1/3/5
1/3/5/7
1/3/6

请注意,这是一个字母排序,所以 11 会出现在 2 之前。但是,你说你不关心兄弟排序。当然,我会将其重写为嵌套集;)

【讨论】:

我可能会将其重写为嵌套集,因为我有很多短树。事情是我的数据已经是自然编码的“物化路径”(域名准确地说是 a.b.c)。我将不得不考虑一段时间,因为我不太确定它在一般情况下是否有效。【参考方案2】:

这将按您的“祖先”的最后一个数字排序

select *, 
Substring(ancestry,LEN(ancestry) - Charindex('/',Reverse(ancestry))+2, LEN(ancestry)) as END_CHAR
from nodes
order by END_CHAR desc

我没有尝试使用大于 9 的数字,您可能需要强制转换为 int

【讨论】:

对不起,刚刚意识到这并不能回答你的问题,我误解了。生病留下查询,它可能会给你一些想法。

以上是关于从使用物化路径编码树的表中选择,按深度优先排序(无递归/ltree)的主要内容,如果未能解决你的问题,请参考以下文章

深度优先搜索算法解释下?

深度优先搜索原理与实践(java)

樱桃季——用深度优先算法如何吃樱桃

二叉树13:二叉树的所有路径

强!深度优先遍历求二叉树的直径

基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)