假设有一个名为tree_node
的表,它具有名为id
的主键,并且有一个名为parent_id
的可为空的列,表中嵌入了树结构(或森林),如何计算一个树的深度在SQL中有效的方式在树/森林节点?SQL中的树深度
SQL中的树深度
回答
您将需要递归功能。使用递归查询,这将是:
WITH RECURSIVE node_ancestors(node_id, parent_id) AS (
SELECT id, id FROM tree_node WHERE id IN (1, 2, 3)
UNION ALL
SELECT na.node_id, tree_node.parent_id
FROM node_ancestors AS na, tree_node
WHERE tree_node.id = na.parent_id AND tree_node.parent_id IS NOT NULL
)
SELECT node_id, COUNT(parent_id) AS depth FROM node_ancestors GROUP BY node_id;
其他选项都在做递归存储过程,在做应用程序的递归和递归限制的数量和使用大量的联接。 (最后一个选项对于非平凡的深度来说效率并不高)
如果深度是无限的,那么问题是递归的,并且没有真正的简单高效的解决方案。 (可能有简单的XOR高效解决方案。)如果您有模式控制权,并且需要定期访问这类数据,那么您可以将表重构为嵌套集,并为每个元素左右包含边界。这将允许你来计算节点的深度与基本条件,一个单一的查询,约为:
select count(*) from tree_node
where left < myLeft
and right > myRight
一种常见的方法来处理树木,除了KEY和家长的定期专栏,你也有一个PATH类型的列,它包含一个字符串值,包含组成路径的节点的键,从根节点到节点本身,由不允许成为键的一部分的字符分隔本身。
让我给你举个例子:
KEY PARENT PATH
1 - *1*
2 1 *1*2*
3 1 *1*3*
4 3 *1*3*4*
5 1 *1*5*
6 5 *1*5*6*
这主要与不改变太多,像部门层次结构或类似的树木中。
我知道这样的字符串并不完全遵循规范化理论,因为它似乎使多个规则(多键,多值字段等)无效,但它在许多情况下非常有用,包括你要求的一个。
在你的情况下,你只需要检索有问题的节点的TREE值,根据最简单的方法,或者计算分隔符的数量,或者用替换函数删除它们,然后计算长度。
这里的SQL给你的节点上面的列表,它们的深度:
select KEY, PARENT, LEN(PATH)-LEN(REPLACE(PATH, '*', ''))-1 as DEPTH
from NODES
注意,这种方法不需要通过递归SQL数据库引擎的任何特殊语法或支持,使其非常很好地索引。
除了不使多值字段失效,因为它仍然只有一个特定的路径,一个值。另外,在存储路径的同时,您可以计算深度一次,并存储该深度,如果它将成为一个常见要求。 – 2009-08-25 21:12:03
+1,这是我最喜欢的树方法。 – RedFilter 2009-08-25 21:21:03
- 1. 找到深度的树haskell
- 2. 确定树的深度
- 3. 找到树的深度?
- 4. 树叶上的二叉树深度
- 5. 在SQL中建模一个固定深度的树
- 6. 深度在树形结构中的BigQuery
- 7. 从nltk树中获取词的深度
- 8. 二叉树中节点的深度
- 9. 使用深度树的高度
- 10. 最大树深度在Haskell
- 11. 测试深度优先树
- 12. Symfony2树枝无限深度
- 13. 查询XML片段在SQL Server中,无论XML树深度
- 14. 在Python中修复深度树
- 15. 给定深度处的子树中的节点数,给定主树中所有节点的深度
- 16. 计算受限深度树中子树的数量
- 17. 将文件保存到树给定的树未知树深度
- 18. 二叉树的最小深度
- 19. B型树的最大深度
- 20. MYSQL和闭合表树的深度
- 21. 查找二叉树的最大深度
- 22. 具有预定义深度的D3树
- 23. 寻找树的最大深度
- 24. 查找树的最大深度
- 25. 树视图节点的深度复制
- 26. 找到最小化树深度的根
- 27. 给定树结构的最大深度
- 28. QTreeView/QFileSystemModel:如何限制树的深度?
- 29. 树的最大深度,使用队列
- 30. 丰富的面孔深度树
不错的功能。不幸的是没有出现在所有的SQL实现上 – Marian 2009-08-25 21:47:20