使用CTE获取emp的层次结构,而不管位置如何

时间:2019-03-17 21:13:03

标签: sql sql-server

我正在考虑使用CTE创建层次结构查询。但是,我在where子句中缺少某些内容,查询应该返回员工的完整层次结构

这是我创建的 a SQL fiddle

预期结果:

对于id = 3,我应该得到以下结果:

ParentEmpId Id          Name 
----------- ----------- -----
NULL        1           A    
1           3           C    
3           6           F     

对于id = 2,我应该得到以下结果:

ParentEmpId Id          Name 
----------- ----------- -----
NULL        1           A    
1           2           B    
2           4           D     
2           5           E     

3 个答案:

答案 0 :(得分:2)

从您的预期输出看来,您既需要id的孩子,又需要他们的父母。因此,您需要为孩子建立一个层次结构,为父母建立一个层次结构:

WITH EmpCTE(ParentEmpId, Id, [Name], [Level]) AS
(
    SELECT ParentEmpId, Id, [Name], 0 AS [Level]
    FROM emp
    WHERE id=3
         UNION ALL
    SELECT E.ParentEmpId, E.Id, E.[Name], [Level] + 1
    FROM emp E
        INNER JOIN EmpCTE empCTE
        ON E.Id = EmpCTE.ParentEmpId 
),
 EmpCTE2(ParentEmpId, Id, [Name], [Level]) AS
(
    SELECT ParentEmpId, Id, [Name], 0 AS [Level]
    FROM emp
    WHERE id=3
         UNION ALL
    SELECT E.ParentEmpId, E.Id, E.[Name], [Level] + 1
    FROM emp E
        INNER JOIN EmpCTE2 empCTE2
        ON E.ParentEmpId = EmpCTE2.Id 
)
Select * from (
select * from EmpCTE 
Union 
select * from EmpCTE2 ) a
order by name

答案 1 :(得分:0)

您正在使用的当前CTE会生成给定id降序层次结构,而不是 parent 层次结构。

一种解决方案是创建第二个递归CTE以生成父层次结构,然后分别UNION,如下所示:

WITH EmpCTE(ParentEmpId, Id, [Name], [Level]) AS
(
    SELECT ParentEmpId, Id, [Name], 0 AS [Level]
    FROM emp
    WHERE id = 2
    UNION ALL
    SELECT E.ParentEmpId, E.Id, E.[Name], [Level] + 1
    FROM emp E
        INNER JOIN EmpCTE empCTE
        ON E.ParentEmpId = EmpCTE.id
),
EmpCTE2(ParentEmpId, Id, [Name], [Level]) AS
(
    SELECT ParentEmpId, Id, [Name], 0 AS [Level]
    FROM emp
    WHERE id = 2
    UNION ALL
    SELECT E.ParentEmpId, E.Id, E.[Name], [Level] + 1
    FROM emp E
        INNER JOIN EmpCTE2 empCTE2
        ON E.id = EmpCTE2.ParentEmpId
)
SELECT * FROM EmpCTE
UNION 
SELECT * FROM EmpCTE2
ORDER BY [name]

在此 updated DB Fiddle 中,当给定id = 2时,查询返回:

ParentEmpId  Id  Name  Level
(null)       1   A     1
1            2   B     0
2            4   D     1
2            5   E     1

答案 2 :(得分:0)

为什么不这样呢?

select data.*
from emp e
  cross apply (
    select * 
    from emp e1
    where e1.Id=e.Id
    union all
    select *
    from emp e2
    where e2.ParentEmpId=e.Id
    union all
    select e4.*
    from emp e3
      join emp e4
        on e3.ParentEmpId=e4.Id
    where e3.Id=e.Id
  ) data
where e.Id=3