我的Names数据库表中具有以下格式的数据:
Names
ID | Name | ParentID 1 | Parent 1 | 0 2 | Parent 2 | 0 3 | Parent 1 Child 1 | 1 4 | Parent 2 Child 1 | 2 5 | Parent 1 Child 1 Child | 3 6 | Parent 2 Child 1 Child 1 | 4 7 | Parent 2 Child 1 Child 2 | 4
该ParentID列将来自该列的数据ID作为父记录。ParentID带有0值的表示根项目。我需要编写查询以按以下顺序获取数据:
ParentID
ID
0
ID | Name | ParentID 1 | Parent 1 | 0 3 | Parent 1 Child 1 | 1 5 | Parent 1 Child 1 Child | 3 2 | Parent 2 | 0 4 | Parent 2 Child 1 | 2 6 | Parent 2 Child 1 Child 1 | 4 7 | Parent 2 Child 1 Child 2 | 4
我需要得到根记录(与记录ParentID为0),然后是所有child和sub- children这根记录,然后获得下根的记录,然后child和sub-children在这个根记录等等。
child
sub- children
sub-children
我在这里提出的解决方案使用了物化路径的概念。以下是使用样本数据的实例化路径的示例。我希望它可以帮助您理解物化路径的概念:
+----+--------------------------+----------+------------------+ | ID | Name | ParentID | MaterializedPath | +----+--------------------------+----------+------------------+ | 1 | Parent 1 | 0 | 1 | | 2 | Parent 2 | 0 | 2 | | 4 | Parent 2 Child 1 | 2 | 2.4 | | 6 | Parent 2 Child 1 Child 1 | 4 | 2.4.6 | | 7 | Parent 2 Child 1 Child 2 | 4 | 2.4.7 | | 3 | Parent 1 Child 1 | 1 | 1.3 | | 5 | Parent 1 Child 1 Child | 3 | 1.3.5 | +----+--------------------------+----------+------------------+
每个节点N都有一个实例化路径,该路径告诉您从根节点到该节点的路径N。可以构建连接节点ID的连接。例如,5要从其根节点开始到达节点,请访问node 1,node3和node 5,因此node的5物化路径为1.3.5
N
5
1
3
1.3.5
巧合的是,您要查找的订单可以通过实现路径来实现。
在前面的示例中,实例化路径是buit连接字符串,但是出于多种原因,我更喜欢二进制连接。
要构建物化路径,您需要以下递归CTE:
CREATE TABLE Tree ( ID int NOT NULL CONSTRAINT PK_Tree PRIMARY KEY, Name nvarchar(250) NOT NULL, ParentID int NOT NULL, ) INSERT INTO Tree(ID, Name, ParentID) VALUES (1, 'Parent 1', 0), (2, 'Parent 2', 0), (3, 'Parent 1 Child 1', 1), (4, 'Parent 2 Child 1', 2), (5, 'Parent 1 Child 1 Child', 3), (6, 'Parent 2 Child 1 Child 1', 4), (7, 'Parent 2 Child 1 Child 2', 4) GO WITH T AS ( SELECT N.ID, N.Name, N.ParentID, CAST(N.ID AS varbinary(512)) AS MaterializedPath FROM Tree N WHERE N.ParentID = 0 UNION ALL SELECT N.ID, N.Name, N.ParentID, CAST( T.MaterializedPath + CAST(N.ID AS binary(4)) AS varbinary(512) ) AS MaterializedPath FROM Tree N INNER JOIN T ON N.ParentID = T.ID ) SELECT * FROM T ORDER BY T.MaterializedPath
结果:
+----+--------------------------+----------+----------------------------+ | ID | Name | ParentID | MaterializedPath | +----+--------------------------+----------+----------------------------+ | 1 | Parent 1 | 0 | 0x00000001 | | 3 | Parent 1 Child 1 | 1 | 0x0000000100000003 | | 5 | Parent 1 Child 1 Child | 3 | 0x000000010000000300000005 | | 2 | Parent 2 | 0 | 0x00000002 | | 4 | Parent 2 Child 1 | 2 | 0x0000000200000004 | | 6 | Parent 2 Child 1 Child 1 | 4 | 0x000000020000000400000006 | | 7 | Parent 2 Child 1 Child 2 | 4 | 0x000000020000000400000007 | +----+--------------------------+----------+----------------------------+
上面的递归CTE从根节点开始。计算根节点的物化路径非常简单,它是节点本身的ID。在下一次迭代中,CTE将根节点与其子节点连接在一起。子节点CN的实例化路径是其父节点的实例化路径与节点PNID的串联CN。随后的迭代在树上向下移动一级,直到到达叶节点为止。
CN
PN