用于在列中构建层次结构的SQL查询

时间:2017-09-15 18:41:25

标签: sql sql-server

我需要一些基本SQL查询的帮助。

我在SQL Server 2012中有一个表EmpIDManagerID。我想构建一个查询来创建一个表格,该表格将数据显示为Emp IDManager IDManager 1(最高层次结构),Manager 2Manager 3,直到当前的经理ID。

我不知道从哪里开始,请指教。

谢谢

1 个答案:

答案 0 :(得分:1)

以下情况应该至少让你朝着正确的方向前进......

对于想要一起玩的人,我已经发布了tfn_Tally和FirstName&的脚本。这里的姓氏表... https://www.dropbox.com/s/cagt1875bkuahwy/Employee%20Hiearchy%20Test%20Objects.sql?dl=0

IF OBJECT_ID('tempdb..#TestData', 'U') IS NULL
BEGIN   -- DROP TABLE #TestData
    CREATE TABLE #TestData (
        EmployeeID INT NOT NULL PRIMARY KEY CLUSTERED,
        FirstName VARCHAR(30) NOT NULL,
        LastName VARCHAR(30) NOT NULL,
        ManagerID INT NOT NULL 
        );

    INSERT #TestData (EmployeeID, FirstName, LastName, ManagerID)
    SELECT
        EmployeeID = t.n,
        fnx.FirstName,
        lnx.LastName,
        ManagerID = CASE WHEN t.n = 1 THEN 0 ELSE m.ManagerID END
    FROM
        dbo.tfn_Tally(50, 1) t
        CROSS APPLY ( VALUES (ABS(CHECKSUM(NEWID())) % ISNULL(NULLIF(t.n - 1, 0), 1) + 1) ) m (ManagerID)
        CROSS APPLY ( VALUES (ABS(CHECKSUM(NEWID())) % 500 + 1, ABS(CHECKSUM(NEWID())) % 1000 + 1, ABS(CHECKSUM(NEWID())) % 2)) n (fn, ln, g)
        CROSS APPLY (
            SELECT
                fn.FirstName
            FROM
                dbo.FirstNames fn --WITH (FORCESEEK) --, INDEX (0))
            WHERE
                n.fn = fn.RankNo
                AND CASE WHEN n.g = 0 THEN 'M' ELSE 'F' END = fn.Gender
            ) fnx
        CROSS APPLY (
            SELECT 
                ln.LastName 
            FROM 
                dbo.LastNames ln --WITH (FORCESEEK) --, INDEX (0))
            WHERE 
                n.ln = ln.RankNo
            ) lnx
END;

-- ===========================================================

WITH 
    cte_Recursion AS (
        SELECT 
            td.EmployeeID,
            td.FirstName,
            td.LastName,
            NodeLevel = 1,
            ManagementChain = CAST(td.EmployeeID AS VARCHAR(8000))
        FROM
            #TestData td
        WHERE 
            td.ManagerID = 0
        UNION ALL 
        SELECT 
            td.EmployeeID,
            td.FirstName,
            td.LastName,
            NodeLevel = r.NodeLevel + 1,
            ManagementChain = CAST(CONCAT(r.ManagementChain, ' > ', td.EmployeeID) AS VARCHAR(8000))
        FROM
            cte_Recursion r
            JOIN #TestData td
                ON r.EmployeeID = td.ManagerID
        )
SELECT 
    *
FROM
    cte_Recursion r
ORDER BY 
    r.EmployeeID;

结果...

EmployeeID  FirstName                      LastName                       NodeLevel   ManagementChain
----------- ------------------------------ ------------------------------ ----------- --------------------------------------------------
1           Alexa                          Wang                           1           1
2           Amy                            Cardenas                       2           1 > 2
3           Drake                          Lloyd                          2           1 > 3
4           Jasmin                         Moses                          3           1 > 3 > 4
5           Shayla                         Massey                         4           1 > 3 > 4 > 5
6           Steven                         Cole                           3           1 > 2 > 6
7           Rafael                         Pittman                        4           1 > 2 > 6 > 7
8           Trenton                        Mendez                         5           1 > 3 > 4 > 5 > 8
9           Khalil                         Bray                           3           1 > 3 > 9
10          Edward                         Hubbard                        4           1 > 3 > 4 > 10
11          Ricky                          Harrison                       4           1 > 3 > 9 > 11
12          Joe                            Velasquez                      5           1 > 3 > 4 > 5 > 12
13          Henry                          Kaiser                         4           1 > 3 > 4 > 13
14          Weston                         Grimes                         5           1 > 3 > 9 > 11 > 14
15          Esther                         Rogers                         3           1 > 2 > 15
16          Kenneth                        Price                          5           1 > 3 > 4 > 5 > 16
17          Jesse                          Lambert                        6           1 > 3 > 4 > 5 > 16 > 17
18          Jenna                          Perry                          4           1 > 2 > 6 > 18
19          Joselyn                        Bowman                         3           1 > 3 > 19
20          Scarlett                       Green                          5           1 > 3 > 4 > 5 > 20
21          Lena                           Wolfe                          3           1 > 2 > 21
22          Asher                          Baird                          3           1 > 2 > 22
23          Adam                           Woodward                       3           1 > 3 > 23
24          Adam                           Reed                           5           1 > 3 > 9 > 11 > 24
25          Kendall                        Conway                         6           1 > 3 > 9 > 11 > 24 > 25
26          Charlotte                      Gibson                         7           1 > 3 > 9 > 11 > 24 > 25 > 26
27          Hayley                         Levy                           4           1 > 2 > 21 > 27
28          Kade                           Hogan                          8           1 > 3 > 9 > 11 > 24 > 25 > 26 > 28
29          Juan                           Moreno                         4           1 > 2 > 21 > 29
30          Bridget                        Ochoa                          4           1 > 2 > 21 > 30
31          Tate                           Gonzales                       2           1 > 31
32          Ryder                          Marsh                          5           1 > 3 > 4 > 5 > 32
33          Gavin                          Craig                          5           1 > 2 > 6 > 18 > 33
34          Aniya                          Matthews                       4           1 > 3 > 9 > 34
35          Angie                          Rollins                        6           1 > 3 > 4 > 5 > 32 > 35
36          Hanna                          Golden                         7           1 > 3 > 4 > 5 > 16 > 17 > 36
37          Jimmy                          Hendrix                        6           1 > 3 > 4 > 5 > 32 > 37
38          Leah                           Blackwell                      6           1 > 2 > 6 > 18 > 33 > 38
39          Brady                          Vaughn                         7           1 > 3 > 4 > 5 > 16 > 17 > 39
40          Milo                           Wright                         2           1 > 40
41          Simon                          Lamb                           6           1 > 3 > 9 > 11 > 24 > 41
42          Miguel                         Kennedy                        6           1 > 2 > 6 > 18 > 33 > 42
43          Kayleigh                       Todd                           7           1 > 2 > 6 > 18 > 33 > 38 > 43
44          Allisson                       Townsend                       7           1 > 3 > 9 > 11 > 24 > 25 > 44
45          Ty                             Haynes                         5           1 > 3 > 9 > 11 > 45
46          Angel                          Gay                            6           1 > 2 > 6 > 18 > 33 > 46
47          Reese                          Marshall                       6           1 > 3 > 4 > 5 > 12 > 47
48          Maria                          Howard                         8           1 > 3 > 4 > 5 > 16 > 17 > 36 > 48
49          Ella                           Mcgee                          9           1 > 3 > 9 > 11 > 24 > 25 > 26 > 28 > 49
50          Cheyanne                       Estes                          4           1 > 2 > 6 > 50

编辑...按名称拆分管理链...(使用原始#TestData)

IF OBJECT_ID('tempdb..#RecursionResults', 'U') IS NOT NULL 
DROP TABLE #RecursionResults;
GO 

WITH 
    cte_Recursion AS (
        SELECT 
            td.EmployeeID,
            EmployeeName = CONCAT(td.FirstName + ' ', td.LastName),
            NodeLevel = 1,
            ManagementChain = CAST(CAST(CONCAT(td.FirstName + ' ', td.LastName) AS BINARY(61)) AS VARBINARY(MAX))
        FROM
            #TestData td
        WHERE 
            td.ManagerID = 0
        UNION ALL 
        SELECT 
            td.EmployeeID,
            EmployeeName = CONCAT(td.FirstName + ' ', td.LastName),
            NodeLevel = r.NodeLevel + 1,
            ManagementChain = CAST(CONCAT(r.ManagementChain, CAST(CONCAT(td.FirstName + ' ', td.LastName) AS BINARY(61))) AS VARBINARY(MAX))
        FROM
            cte_Recursion r
            JOIN #TestData td
                ON r.EmployeeID = td.ManagerID
        )
SELECT 
    r.EmployeeID,
    r.EmployeeName,
    r.NodeLevel,
    r.ManagementChain
    INTO #RecursionResults
FROM
    cte_Recursion r
ORDER BY 
    r.EmployeeID;

----------------------------------

DECLARE 
    @MaxNode INT,
    @MgtColumList NVARCHAR(4000),
    @sql NVARCHAR(4000),
    @DeBug BIT = 0; -- 1=PRINT @sql... 2=EXEC @sql

SELECT @MaxNode = MAX(rr.NodeLevel) FROM #RecursionResults rr;

SELECT 
    @MgtColumList = CONCAT(@MgtColumList, N',
    MgrLevel_', t.n + 1, N' = CAST(SUBSTRING(rr.ManagementChain, ', (t.n * 61) + 1, N', ', 61, N') AS VARCHAR(61))')
FROM 
    dbo.tfn_Tally(@MaxNode, 0) t;

SET @sql = CONCAT(N'
SELECT 
    rr.EmployeeID,
    rr.EmployeeName,
    rr.NodeLevel',
    @MgtColumList, N'
FROM 
    #RecursionResults rr;');

IF @DeBug = 1
BEGIN 
    PRINT(@sql);
END;
ELSE 
BEGIN
    EXEC sys.sp_executesql @sql;
END;

结果样本......

    EmployeeID  EmployeeName                                                  NodeLevel   MgrLevel_1                                                    MgrLevel_2                                                    MgrLevel_3                                                   
----------- ------------------------------------------------------------- ----------- ------------------------------------------------------------- ------------------------------------------------------------- -------------------------------------------------------------
1           Theodore Cain                                                 1           Theodore Cain                                                                                                                                                                            
2           Julianna Sanders                                              2           Theodore Cain                                                 Julianna Sanders                                                                                                           
3           Caroline Wilkinson                                            3           Theodore Cain                                                 Julianna Sanders                                              Caroline Wilkinson                                           
4           Eleanor Hancock                                               3           Theodore Cain                                                 Julianna Sanders                                              Eleanor Hancock                                              
5           Casey Ware                                                    2           Theodore Cain                                                 Casey Ware                                                                                                                 
6           Jacoby Lyons                                                  4           Theodore Cain                                                 Julianna Sanders                                              Caroline Wilkinson                                           
7           Jaden Stout                                                   2           Theodore Cain                                                 Jaden Stout                                                                                                                
8           Reece Weeks                                                   5           Theodore Cain                                                 Julianna Sanders                                              Caroline Wilkinson                                           
9           Kyleigh Frazier                                               5           Theodore Cain                                                 Julianna Sanders                                              Caroline Wilkinson                                           
10          Nasir Wong                                                    3           Theodore Cain                                                 Casey Ware                                                    Nasir Wong                                                   
11          Sarah Rivas                                                   4           Theodore Cain                                                 Julianna Sanders                                              Eleanor Hancock