T-SQL递归CTE以查找最高的ParentID
昨天的采访中,我被问到一个有趣的问题,那就是如何找到最高的 每行的ParentID 当时我无法回答这个问题,但我在网上找到了解决方案,但我仍然无法理解这个查询是如何工作的 有人能详细解释一下递归CTE是如何工作的吗?谢谢 我在按钮上发布了我提出的示例问题和解决方案 =================================================================T-SQL递归CTE以查找最高的ParentID,sql,sql-server,tsql,Sql,Sql Server,Tsql,昨天的采访中,我被问到一个有趣的问题,那就是如何找到最高的 每行的ParentID 当时我无法回答这个问题,但我在网上找到了解决方案,但我仍然无法理解这个查询是如何工作的 有人能详细解释一下递归CTE是如何工作的吗?谢谢 我在按钮上发布了我提出的示例问题和解决方案 ================================================================= Create table dbo.##Test001 (ID int, Name varchar(10
Create table dbo.##Test001 (ID int, Name varchar(100), ParentID int)
Insert into ##Test001 values (1, 'AA', null), (2, 'BB', 1), (3, 'CC', 2), (4, 'DD', 3)
,(5, 'AAA', null), (6, 'BBB', 5), (7, 'CCC', 6), (8, 'DDD', 7)
;WITH c AS (
SELECT id, parentid, id AS topParentID FROM ##Test001
WHERE ParentID is null
UNION ALL
SELECT T.id, T.parentid, c.topparentid FROM ##Test001 AS T
INNER JOIN c
ON T.parentid = c.id
WHERE T.id <> T.parentid
)
SELECT id, topparentid FROM c
ORDER BY id
提醒自己使用函数进行递归可能会有所帮助
-- pseudo code
void numberFunction(int i) {
Print i
increment i
if(i<10) {
numberFunction(i);
}
}
递归公共表表达式CTE的结构为:
作为递归查询输入的锚查询
联合所有
递归查询-当递归查询返回空集时停止
请注意,在math/pseudo code函数中,我们增加或减少一个变量,并检查退出状态
在该查询中,当为匹配的T.parentid返回T.id时,递增/递减功能位于递归查询中
此查询的退出状态为递归查询返回空集时
WITH c AS
(
SELECT
id, parentid, id AS topParentID
FROM
#Test001
WHERE
ParentID is null
UNION ALL
SELECT
T.id, T.parentid, c.topparentid
FROM
#Test001 AS T
INNER JOIN
c ON T.parentid = c.id
WHERE
T.id <> T.parentid
)
SELECT id, topparentid
FROM c
ORDER BY id
然后将该输出与T.parentid=c.id上的临时表Test001 T联接
ID Name ParentID
1 AA NULL
2 BB 1
3 CC 2
4 DD 3
5 AAA NULL
6 BBB 5
7 CCC 6
8 DDD 7
SELECT T.id, T.parentid, c.topparentid
FROM #Test001 AS T
INNER JOIN c ON T.parentid = c.id
T.id T.parentid c.topparentid
2 1 1
6 5 5
您可以继续剩余id/父id组合的过程
UNION ALL组合锚查询和所有递归查询的所有结果。UNION ALL可用于具有相同数量的参数和类似类型的查询
资料来源:
id parentid topParentID
1 NULL 1
5 NULL 5
ID Name ParentID
1 AA NULL
2 BB 1
3 CC 2
4 DD 3
5 AAA NULL
6 BBB 5
7 CCC 6
8 DDD 7
SELECT T.id, T.parentid, c.topparentid
FROM #Test001 AS T
INNER JOIN c ON T.parentid = c.id
T.id T.parentid c.topparentid
2 1 1
6 5 5