【发布时间】:2021-06-15 14:22:56
【问题描述】:
我有一个闭包表,其中可能有多个父级,关联的数据表如下所示:
CREATE TABLE [data] (
id int IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(100)
)
CREATE TABLE closure (
id int IDENTITY(1,1) PRIMARY KEY,
[src_id] int,
[dst_id] int,
[depth] int,
FOREIGN KEY ([src_id]) REFERENCES [data](id),
FOREIGN KEY ([dst_id]) REFERENCES [data](id)
)
现在我创建了一些看起来像这样的测试数据,DDL 看起来像这样:
数据表
INSERT [data] ([name]) VALUES (N'data1')
INSERT [data] ([name]) VALUES (N'data2')
INSERT [data] ([name]) VALUES (N'data3')
INSERT [data] ([name]) VALUES (N'data4')
INSERT [data] ([name]) VALUES (N'data5')
INSERT [data] ([name]) VALUES (N'data6')
闭包表
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 1, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (2, 2, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (3, 3, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (4, 4, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (5, 5, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (6, 6, 0)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 2, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (2, 5, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 5, 2)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (5, 6, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (2, 6, 2)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 6, 3)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 3, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (3, 4, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 4, 2)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (4, 5, 1)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (3, 5, 2)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 5, 3)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (4, 6, 2)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (3, 6, 3)
INSERT [closure] ([src_id], [dst_id], [depth]) VALUES (1, 6, 4)
现在我想要的是一个查询,它输出每个数据集的每个路径,直到该路径不再有src_id,
我想用这个语句查询:
;WITH hierarchy_cte AS (
SELECT [data].id, [data].name, CAST ([data].name AS VARCHAR(100)) AS path , 0 as pathDepth
FROM closure
INNER JOIN [data]
ON [data].id = closure.src_id
WHERE closure.depth = 0
UNION ALL
SELECT closure.src_id, hierarchy_cte.name, CAST(([srcdata].name + ' / ' + hierarchy_cte.path) AS VARCHAR(100)) , hierarchy_cte.pathDepth + 1
FROM closure
INNER JOIN [data] srcdata
ON srcdata.id = closure.src_id
INNER JOIN [data]
ON [data].id = closure.dst_id
inner join [hierarchy_cte]
ON [data].id = hierarchy_cte.id
AND closure.depth = 1
)
SELECT * FROM hierarchy_cte
结果如下所示:
+----+-------+---------------------------------------+-----------+
| id | name | path | pathDepth |
+----+-------+---------------------------------------+-----------+
| 1 | data1 | data1 | 0 |
| 2 | data2 | data2 | 0 |
| 3 | data3 | data3 | 0 |
| 4 | data4 | data4 | 0 |
| 5 | data5 | data5 | 0 |
| 6 | data6 | data6 | 0 |
| 5 | data6 | data5 / data6 | 1 |
| 2 | data6 | data2 / data5 / data6 | 2 |
| 4 | data6 | data4 / data5 / data6 | 2 |
| 3 | data6 | data3 / data4 / data5 / data6 | 3 |
| 1 | data6 | data1 / data3 / data4 / data5 / data6 | 4 |
| 1 | data6 | data1 / data2 / data5 / data6 | 3 |
| 2 | data5 | data2 / data5 | 1 |
| 4 | data5 | data4 / data5 | 1 |
| 3 | data5 | data3 / data4 / data5 | 2 |
| 1 | data5 | data1 / data3 / data4 / data5 | 3 |
| 1 | data5 | data1 / data2 / data5 | 2 |
| 3 | data4 | data3 / data4 | 1 |
| 1 | data4 | data1 / data3 / data4 | 2 |
| 1 | data3 | data1 / data3 | 1 |
| 1 | data2 | data1 / data2 | 1 |
+----+-------+---------------------------------------+-----------+
我认为我的陈述将沿着所有可能的路径进行,并在没有更多 src_id 时结束。我只是卡住了。
我想要的结果是:
+----+-------+---------------------------------------+-----------+
| id | name | path | pathDepth |
+----+-------+---------------------------------------+-----------+
| 1 | data1 | data1 | 0 |
| 2 | data2 | data1 / data2 | 1 |
| 3 | data3 | data1 / data3 | 1 |
| 4 | data4 | data1 / data3 / data4 | 2 |
| 5 | data5 | data1 / data3 / data4 / data5 | 3 |
| 5 | data5 | data1 / data2 / data5 | 2 |
| 6 | data6 | data1 / data3 / data4 / data5 / data6 | 4 |
| 6 | data6 | data1 / data2 / data5 / data6 | 3 |
+----+-------+---------------------------------------+-----------+
这个查询似乎并不难,但我就是想不通。
【问题讨论】:
标签: sql sql-server tsql recursion common-table-expression