Get all employees under manager with CTE

蹲街弑〆低调 提交于 2019-12-03 18:12:26

问题


I have a table which has employee details

EmpId ManagerId Level Value
1      0         5     CEO
2      1         4     EMP
3      1         4     ORG
4      2         3     NULL
5      2         3     NULL
6      2         2     NULL
7      1         1     NULL
8      5         0     NULL

Now, I have to start wil Employee Id 2 and found all it's low level hirerachy (i.e. 2, 4, 5, 6, 8) and assign them value same as "2" (i.e. EMP).

Expected output :

  EmpId ManagerId Level Value
    1      0         5     CEO
    2      1         4     EMP
    3      1         4     ORG
    4      2         3     EMP
    5      2         3     EMP
    6      2         2     EMP
    7      1         1     NULL
    8      5         0     EMP

What I am trying:

    ; WITH LevelHire AS
(
        SELECT EmpId, ManagerId,Level
        FROM EmployeeTable
        WHERE EmpId =2
        UNION ALL
        SELECT Lh.EmpId,  RC.ManagerId, Lh.Level
        FROM LevelHire LH
        INNER JOIN [EmployeeTable] RC
        ON LH.EmpId= RC.EmpId

)

SELECT * FROM LevelHire
option (maxrecursion 0)

How can I achieve the same?


回答1:


you can try something like this

;WITH EmployeeTable AS 
(
SELECT 1 EmpId,0 ManagerId ,   5 Level ,'CEO' Value
UNION ALL SELECT 2,1,   4,'EMP'
UNION ALL SELECT 3,1,   4,'ORG'
UNION ALL SELECT 4,2,   3,NULL
UNION ALL SELECT 5,2,   3,NULL
UNION ALL SELECT 6,2,   2,NULL
UNION ALL SELECT 7,1,   1,NULL
UNION ALL SELECT 8,5,   0,NULL
),LevelHire AS
(
        SELECT EmpId, ManagerId,Level,Value
        FROM EmployeeTable
        WHERE EmpId = 2
        UNION ALL
        SELECT RC.EmpId,  RC.ManagerId, Lh.Level,LH.Value
        FROM LevelHire LH
        INNER JOIN [EmployeeTable] RC
        ON LH.EmpId= RC.ManagerId
)
SELECT  E.EmpId, E.ManagerId,E.Level,ISNULL(E.Value ,LH.Value) Value
FROM EmployeeTable E
    LEFT JOIN LevelHire LH
    ON E.EmpId = LH.EmpId



回答2:


Time to learn about hierarchyid. First, some code:

IF object_id('tempdb.dbo.#employees') IS NOT NULL
    DROP TABLE #employees;
go
WITH Employees AS (
    SELECT  *
    FROM    ( VALUES 
        ( 1, NULL, 5, 'CEO'), 
        ( 2, 1, 4, 'EMP'), 
        ( 3, 1, 4, 'ORG'),
        ( 4, 2, 3, NULL ), 
        ( 5, 2, 3, NULL ), 
        ( 6, 2, 2, NULL ),
        ( 7, 1, 1, NULL ), 
        ( 8, 5, 0, NULL ) 
    ) AS x ( EmpId, ManagerId, Level, Value ) 
), rcte AS (
    SELECT e.EmpId ,
           e.ManagerId ,
           e.Level ,
           e.Value,
           CAST('/' + CAST(e.EmpId AS VARCHAR) + '/' AS VARCHAR(MAX)) AS h
    FROM Employees AS e
    WHERE e.ManagerId IS NULL

    UNION ALL

    SELECT e.EmpId ,
           e.ManagerId ,
           e.Level ,
           e.Value ,
           m.h + CAST(e.EmpId AS VARCHAR) + '/' AS h
    FROM Employees AS e
    JOIN rcte AS m
        ON e.ManagerId = m.EmpId
)
SELECT rcte.EmpId ,
       rcte.ManagerId ,
       rcte.Level ,
       rcte.Value ,
       CAST(rcte.h AS HIERARCHYID) AS h
INTO #employees
FROM rcte;
GO

SELECT  e.EmpId ,
        e.ManagerId ,
        e.Level ,
        e.Value ,
        e.h.ToString() AS h
FROM    #employees AS e
JOIN    #employees AS m
        ON e.h.IsDescendantOf(m.h) = 1
WHERE   m.EmpId = 1

SELECT  m.EmpId ,
        m.ManagerId ,
        m.Level ,
        m.Value ,
        m.h.ToString() AS h
FROM    #employees AS e
JOIN    #employees AS m
        ON e.h.IsDescendantOf(m.h) = 1
WHERE   e.EmpId = 8

While I needed a recursive CTE to actually establish the hierarchy, any of the actual queries of the form "who does this person report to?" and "who reports to this person?" are ultimately satisfied from the persisted hierarchy in the #employees table. The two queries at the end show how to traverse the hierarchy in either direction. This sort of thing is important if your hierarchy is large (wide, deep, or both). You do need to maintain it when the org chart changes, but that's a one-time operation. The querying of the data should be fast because the lineage is persisted with the employee record.

Incidentally, your Level column is a bit odd to me. Specifically, it seems backwards (i.e. CEO has the highest level). I say this because if/when you add another level to the org chart, you'll need to re-level everyone from the CEO down. If you have the CEO have the lowest level, you just tack that level onto the bottom and don't have to re-level anyone.



来源:https://stackoverflow.com/questions/29559827/get-all-employees-under-manager-with-cte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!