我在数据库的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
的{{1}}表示根项。我需要编写一个查询来按以下顺序获取数据:
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
为0),然后是此根记录的所有ParentID
和child
,然后获取下一个根记录,后跟{此根记录的{1}}和sub-children
等等。
答案 0 :(得分:7)
我在这里提出的解决方案使用了物化路径的概念。以下是使用示例数据的物化路径示例。我希望它能帮助你理解物化路径的概念:
+----+--------------------------+----------+------------------+
| 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
,请访问节点1
,节点3
和节点5
,以便节点5
具体化路径是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
的实现路径是其父节点PN
的实现路径和节点CN
的ID的串联。后续迭代在树上向下推进一级,直到到达叶节点。