与此问题类似: How do I query for all the nodes between two nodes in a tree?
但是我没有有一个闭包(flattened)表,一个孩子可以有很多父母,并且ID遍历不一定是有序的。嵌套深度没有限制。
假设循环引用是不可能的...... 我想返回遍历层次结构所需的所有行。
假设下表:
ParentID ID RowNumber(Reference)
1 2 1
2 4 2
4 3 3
3 5 4
1 6 5
6 7 6
2 8 7
3 9 8
1 8 9
6 8 10
给定1
我如何编写单个查询来返回所有行(获取所有后代的关系)?
同样,给定2
我会期望行2,3,4,7,8
给定6
我会期望第6行和第10行
偶然的误报是可以接受的,因为结果中有重复的行。丢失的行是不可接受的
在MSAccess和SQL Server 2000 +中实现
答案 0 :(得分:3)
对于SQL Server:Adjacency list vs. nested sets: SQL Server
对于Jet / MS Access,递归查询不是一个选项,因此nested sets将是可行的方法。样本:http://www.mvps.org/access/queries/qry0023.htm
嵌套集的一些背景知识:
要实现嵌套集解决方案,您需要在表中添加和维护另外两列:Lt
和Rt
(分别为左侧和右侧)。通过执行修改的预订树遍历来为这些列分配值,从而填充这些列。使用递归函数可以最轻松地完成此操作。然后,您可以使用左右值来确定SELECT时间的后代。
每当数据发生变化时,需要进行更多的处理,但在检索数据时执行速度要快得多。
这个概念有点不直观,当然有一个学习曲线,但我亲自使用它的效果很好。据我所知,这是在Jet(MS Access数据库引擎)中仅使用SELECT查询后实现目标的唯一方法。
示例嵌套集解决方案:
ParentID ID Lt Rt RowNumber(Reference)
Null 1 1 18 0
1 2 2 13 1
2 4 3 10 2
4 3 4 9 3
3 5 5 6 4
1 6 14 17 5
6 7 15 16 6
2 8 11 12 7
3 9 7 8 8
然后获取ID 2
的所有后代:
SELECT * FROM Tbl WHERE Lt Between 2 And 13
以下是图形化的树状结构:
答案 1 :(得分:1)
由于您需要为节点可以具有多个父节点的数据建模,因此嵌套集/ MPTT解决方案将无法工作。另一种选择是使用closure table。
你会创建一个额外的表,为每个祖先的后代保留一对项目(反之亦然):
AncID DesID 1 2 1 6 1 4 1 8 1 7 1 3 1 5 1 9 2 4 2 8 2 3 2 5 2 9 4 3 4 5 4 9 3 5 3 9 6 7
然后您将使用联接来获取所需的项目:
SELECT *
FROM Tbl INNER JOIN Closure ON Tbl.ID=Closure.DesID
WHERE Closure.AncID = 2
答案 2 :(得分:0)
检查此线程以查看它是否使用ANSI SQL回答您的问题。基本上,Oracle使用CONNECT BY子句有一个很好的方法,你需要使用ANSI SQL复制它。 Simulation of CONNECT BY PRIOR of ORACLE in SQL SERVER