Get all employees under manager with CTE

前端 未结 2 821

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条回答
  • 2020-12-21 21:04

    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.

    0 讨论(0)
  • 2020-12-21 21:08

    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
    
    0 讨论(0)
提交回复
热议问题