我需要帮助理解此查询的递归部分:
WITH EmpsCTE AS
(
SELECT empid, mgrid, firstname, lastname
FROM HR.Employees
WHERE empid = 2
UNION ALL
SELECT C.empid, C.mgrid, C.firstname, C.lastname
FROM EmpsCTE AS P
JOIN HR.Employees AS C
ON C.mgrid = P.empid
)
SELECT empid, mgrid, firstname, lastname
FROM EmpsCTE;
上面的查询结果如下所示。
这是HR.employees表的图片。
我无法理解为什么代码会递归。我理解这个表如何输出直接经理是经理的所有员工,其中包含2的empid,但我不明白为什么代码会在第2章的情况下递归并生成员工的下属。
答案 0 :(得分:1)
使用CTE的递归查询(如上所述)通常由CTE定义中的两部分组成。第一个获取您将从(锚记录)
开始递归的记录SELECT empid, mgrid, firstname, lastname
FROM HR.Employees
WHERE empid = 2
这将选择您最顶级的员工。
然后要实现递归,你需要UNION
使用CTE查询的第二部分(获取递归记录):
UNION ALL
SELECT C.empid, C.mgrid, C.firstname, C.lastname
FROM EmpsCTE AS P
JOIN HR.Employees AS C
ON C.mgrid = P.empid
这里最重要的一点是:
EmpsCTE
)中使用的别名加入源表(HR.Employees
)。这将产生递归,因为它将使用源表中的记录连接CTE中已存在的记录。这将完成,直到调用recurive部分不返回任何记录。我还要在enter link description here上粘贴一个关于该主题的部分,以官方的方式解释它:
Transact-SQL中递归CTE的结构类似于其他编程语言中的递归例程。虽然其他语言中的递归例程返回标量值,但递归CTE可以返回多行。
递归CTE由三个元素组成:
- 调用例程。
递归CTE的第一次调用由一个或多个由UNION ALL,UNION,EXCEPT或INTERSECT运算符连接的CTE_query_definition组成。因为这些查询定义构成了CTE结构的基本结果集,所以它们被称为锚成员。 CTE_query_definitions被认为是锚成员,除非它们引用CTE本身。所有锚成员查询定义必须位于第一个递归成员定义之前,并且必须使用UNION ALL运算符将最后一个锚成员与第一个递归成员连接。
- 递归调用例程。
递归调用包括由引用CTE本身的UNION ALL运算符连接的一个或多个CTE_query_definition。这些查询定义称为递归成员。
- 终止检查。
终止检查是隐含的;当前一次调用没有返回任何行时,递归停止。