2017-08-30 153 views
0

我想运行一个递归CTE这样我就可以得到表2之间所有可能的关系,用表提供的信息1.SQL递归:获得父母和后代

表1:

Employee | ReportsTo 
a   NULL 
b   a 
c   b 
d   c 

表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 

返回:

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

举了几个例子来说明我的问题,注意,我缺少的“d”间接雇员“B”举报员工之间的关系。或员工“d”间接向员工“a”报告。

+0

@Amit我不认为在链接中提供的答案正是我所期待的。我想要实现表2中的结果,而不是通过WHERE子句指定Employee或ReportsTo的值。任何其他建议? – Paramus

+0

您正在使用哪个[DBMS](https://en.wikipedia.org/wiki/Database)? –

回答

0

你很近。您需要从您的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 
    ) 

而现在,你把所有的节点/分支机构,则可以选择那些这反映了你想要的适当深度。 (concat还将最终员工添加到树路径中。) 此选择还为顶层节点提供正确的零深度。

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 
0

试试这个。

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;