返回多对多分层树中的所有节点

时间:2011-03-08 19:32:00

标签: sql sql-server ms-access many-to-many hierarchical-data

与此问题类似: 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 +中实现

3 个答案:

答案 0 :(得分:3)

对于SQL Server:Adjacency list vs. nested sets: SQL Server

对于Jet / MS Access,递归查询不是一个选项,因此nested sets将是可行的方法。样本:http://www.mvps.org/access/queries/qry0023.htm

嵌套集的一些背景知识:

要实现嵌套集解决方案,您需要在表中添加和维护另外两列:LtRt(分别为左侧和右侧)。通过执行修改的预订树遍历来为这些列分配值,从而填充这些列。使用递归函数可以最轻松地完成此操作。然后,您可以使用左右值来确定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

以下是图形化的树状结构:

Modified Preorder Tree

答案 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