SQL Server 2008 R2需要帮助理解递归CTE

时间:2014-03-03 19:58:40

标签: sql sql-server recursion

我需要帮助理解此查询的递归部分:

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;

上面的查询结果如下所示。

enter image description here

这是HR.employees表的图片。

enter image description here

Click for enlarged version

我无法理解为什么代码会递归。我理解这个表如何输出直接经理是经理的所有员工,其中包含2的empid,但我不明白为什么代码会在第2章的情况下递归并生成员工的下属。

1 个答案:

答案 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

这里最重要的一点是:

  • 您需要将CTE定义(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。这些查询定义称为递归成员。

     
      
  • 终止检查。
  •   
     

终止检查是隐含的;当前一次调用没有返回任何行时,递归停止。