你可以使用递归函数
一个简单的解释,使用 CTE 的递归函数是一个 common table expression,它在计算时使用它自己。它包括:
- 调用例程。
递归 CTE 的第一次调用
由一个或多个由 UNION ALL 连接的 CTE_query_definitions 组成,
UNION、EXCEPT 或 INTERSECT 运算符。
因为这些查询定义
形成 CTE 结构的基本结果集,它们被称为
锚定成员。
CTE_query_definitions 被视为锚成员
除非他们引用 CTE 本身。
所有锚成员查询
定义必须位于第一个递归成员之前
定义,并且必须使用 UNION ALL 运算符来连接最后一个
锚成员与第一个递归成员。
- 例程的递归调用。
递归调用包括一个或多个
CTE_query_definitions 由引用
CTE 本身。这些查询定义称为递归
成员。
- 终止检查。
终止检查是隐式的;
当前一个没有返回行时递归停止
调用。
参考链接:Recursive query using CTE
Simple Example of Recursive CTE
Cte sql server
DECLARE @SampleData AS TABLE (Id int, Name varchar(10), LinkedId int)
INSERT INTO @SampleData
VALUES (1, 'A', 1), (2, 'B', 2),
(3, 'C', 1),(4, 'D', 3),(5, 'A', 4)
;WITH temp AS
(
SELECT sd.Id, sd.Name, sd.Id AS RootId
FROM @SampleData sd WHERE sd.LinkedId = sd.Id -- Invocation of the routine, in this case it's root node of tree.
UNION ALL
-- Recursive invocation of the routine
SELECT sd.Id, sd.Name, t.RootId AS RootId
FROM temp t
INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id
-- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id.
-- It make recursive query is not an infinitive loop
)
SELECT t.Id, t.Name, t.RootId AS LinkedId
FROM temp t
OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100.
对于新的输出,您可以更改The first invocation of the
recursive CTE
;WITH temp AS
(
SELECT sd.Id, sd.Name, sd.Id AS RootId
FROM @SampleData sd WHERE sd.Id = 3
UNION ALL
-- Recursive invocation of the routine
SELECT sd.Id, sd.Name, t.RootId AS RootId
FROM temp t
INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id
-- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id.
-- It make recursive query is not an infinitive loop
)
SELECT t.Id, t.Name, t.RootId AS LinkedId
FROM temp t
OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100.