SQL递归:获取所有可能的父子关系

SQL Recursion: Obtain all possible relationships between parents and descendants

我想 运行 一个递归 CTE,这样我就可以获得 Table 2,使用 Table 1.

中提供的信息

Table 1:

Employee  | ReportsTo
a           NULL
b           a
c           b
d           c

Table 2:

Employee  | ReportsTo  | depth
a           NULL         0
b           a            1
c           a            2
d           a            3
c           b            1
d           b            2
d           c            1

到目前为止,我有:

with cte
    (Employee
    ,ReportsTo
    ,depth)
as
    (
    select  Employee
            ,ReportsTo
            ,0 as depth
    from    [Table 1]
    where   ReportsTo is null

    UNION ALL

    select  a.Employee
            ,a.ReportsTo
            ,b.depth + 1
    from    cte b
    join [Table 1] a    
            on a.ReportsTo = b.Employee
    )

select  *
from    cte
order by depth

哪个returns:

Employee  | ReportsTo | Depth
a           NULL        0
b           a           1
c           b           2
d           c           3

举几个例子来说明我的问题,请注意我遗漏了员工 "d" 间接向员工 "b" 汇报的关系。或者 Employee "d" 间接向 Employee "a".

汇报

试试这个。

with cte
    (root
    ,Employee
    ,ReportsTo
    ,depth)
as
    (
    select  ReportsTo root
            ,Employee
            ,ReportsTo
            ,0 as depth
    from    [Table 1] t1

    UNION ALL

    select  b.root
            ,a.Employee
            ,a.ReportsTo
            ,b.depth + 1
    from    cte b
    join [Table 1] a    
            on a.ReportsTo = b.Employee
    )

select  distinct Employee , root ReportsTo,  depth+1 depth
from    cte
where depth = 0 or root is not null --  needn't null as a boss but on 0 level
order by depth;

你很接近。您需要从 cte 中删除 where ReportsTo is null 才能获得分支上的所有节点。 (我还添加了一个 concat,因此您可以看到完整的树路径以及顶部节点和员工之间的所有节点。)

WITH cte
    (TopNode
    ,Employee
    ,ReportsTo
    ,Depth
    ,TreePath)
AS
    (
    SELECT ReportsTo AS TopNode
           ,Employee
           ,ReportsTo
           ,0 AS Depth
           ,CAST(ReportsTo AS VARCHAR(max)) AS TreePath
    FROM   #tblTable1

    UNION ALL

    SELECT cte.TopNode
           ,a.Employee
           ,a.ReportsTo
           ,cte.Depth + 1 AS depth
           ,CAST(cte.TreePath + ' -> ' +
            CAST(a.ReportsTo AS VARCHAR(max)) 
            AS VARCHAR(max)) AS TreePath
    FROM #tblTable1 AS a
    inner join cte
       ON cte.Employee = a.ReportsTo
    )

现在您已经拥有所有 nodes/branches,您可以 select 反映您想要的适当深度的那些。 (concat 还将最终员工添加到树路径中。) select 还为您提供了顶部节点的正确深度为零。

SELECT
    cte.Employee
    ,cte.TopNode AS ReportsTo
    ,case when cte.ReportsTo is null
             then cte.Depth 
          else cte.Depth + 1
     end AS Depth
    ,case when cte.ReportsTo is null
             then cte.Employee
          else CAST(cte.TreePath + ' -> ' +
               CAST(cte.Employee AS VARCHAR(max)) 
               AS VARCHAR(max)) 
     end AS TreePath
FROM cte
WHERE
   cte.TopNode is not null
   or cte.ReportsTo is null
ORDER BY
   cte.TopNode
   ,cte.Depth;

结果集为:

Employee  ReportsTo   Depth   TreePath
a         NULL        0       a
b         a           1       a -> b
c         a           2       a -> b -> c
d         a           3       a -> b -> c -> d
c         b           1       b -> c
d         b           2       b -> c -> d
d         c           1       c -> d