SQL递归CTE递归成员循环及Rank计算逻辑疑问
递归CTE运行原理解答
你对锚成员的初始判断是对的:递归CTE第一次执行时,锚成员确实只会返回ManagerID IS NULL的最高级员工行,Rank值为1。你疑惑的点本质是对递归成员的循环执行规则不清晰,核心逻辑如下:
- 递归CTE的递归成员不是只执行一次,而是会循环触发,每次执行时用来关联的
EmployeesCTE不是整个CTE的累计结果,仅为上一轮递归新产出的结果集。 - 每轮递归的产出结果,会同时做两个操作:一是追加到整个CTE的最终结果集里,二是作为下一轮递归时
EmployeesCTE的关联数据。
我们可以用实际执行步骤拆解验证:
- 第一轮执行锚成员,得到结果集R1:仅最高级领导,Rank=1。R1追加到CTE最终结果,同时作为下一轮的输入。
- 第二轮执行递归成员,拿R1和
Employees表做关联,匹配条件是Employees.ManagerID = R1.EmployeeID,得到的是最高级领导的所有直接下属,Rank为R1的Rank+1=2,产出结果集R2。R2追加到CTE最终结果,作为下一轮输入。 - 第三轮执行递归成员,拿R2和
Employees表关联,得到R2里所有员工的直接下属,Rank为2+1=3,产出结果集R3,追加到最终结果,交给下一轮。 - 循环执行以上逻辑,直到某一轮递归执行后没有返回任何行,递归终止。
这个逻辑下不会出现你担心的错误增量问题:因为每轮递归只会处理上一轮新产生的上级员工,只会给这些上级的直接下属计算Rank增量,不会重复处理已经计算过的历史员工行。
你贴的SQL执行后就会返回全公司员工的层级树,Rank值对应员工的组织层级,Rank=1是最高负责人,Rank=2是一级部门负责人,以此类推。
USE Examples; WITH EmployeesCTE AS ( -- 锚成员:获取最高级负责人 SELECT EmployeeID, FirstName + ' ' + LastName As EmployeeName, 1 As Rank FROM Employees WHERE ManagerID IS NULL UNION ALL -- 递归成员:逐层级获取下属 SELECT Employees.EmployeeID, FirstName + ' ' + LastName, Rank + 1 FROM Employees JOIN EmployeesCTE ON Employees.ManagerID = EmployeesCTE.EmployeeID ) SELECT * FROM EmployeesCTE ORDER BY Rank, EmployeeID; SELECT * FROM Employees
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

