2014-03-03 65 views
1

我需要帮助理解这个查询的递归部分:上面如下所示的查询SQL Server 2008 R2中的极品帮助理解递归CTE

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的所有员工,但我不明白为什么代码递归并生成empid 2下的员工的下属。

回答

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中的记录。这将一直执行,直到recive部分的调用不返回任何记录。
  • 作为您的连接条件将员工链接到其经理,递归部分将继续生成记录,只要有新员工在查询已在之前的迭代中返回的那些人员下工作。

让我也粘贴enter link description here一节关于这一主题来解释它的正式方式:

递归CTE的Transact-SQL中的结构类似于其他编程语言中的递归例程。虽然其他语言的递归例程返回标量值,但递归CTE可以返回多行。

递归CTE由三个部分组成:

例程的
  • 调用。

第一次递归CTE的调用由一个或多个由UNION ALL,UNION,EXCEPT或INTERSECT运算符连接的CTE_query_definitions组成。由于这些查询定义形成了CTE结构的基本结果集,因此它们被称为定位成员。 CTE_query_definitions被视为锚定成员,除非他们引用了CTE本身。所有锚定成员查询定义必须位于第一个递归成员定义之前,并且必须使用UNION ALL运算符将最后一个锚定成员与第一个递归成员进行连接。

  • 递归调用例程。

递归调用包括一个或多个引用CTE本身的UNION ALL运算符连接的CTE_query_definitions。这些查询定义被称为递归成员。

  • 终止检查。

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