2017-09-15 81 views
-2

我需要一些基本的SQL查詢幫助。用於在列中構建層次結構的SQL查詢

我在SQL Server 2012中有一個表,其列EmpID,ManagerID。我想建立一個查詢來創建一個表,其中顯示數據爲Emp ID,Manager ID,Manager 1(最高層次),Manager 2,Manager 3,直到當前的經理ID。

我不確定從哪裏開始,請指教。

謝謝

+2

你有什麼已經研究和/或試過嗎? –

+0

研究https://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ –

+0

我已經嘗試完全相同的查詢帖子中提到。與MyCTE AS(SELECT的EmpID,名字,姓氏,經理ID FROM員工 WHERE經理ID IS NULL UNION ALL SELECT 的EmpID,名字,姓氏,經理ID FROM員工 INNER JOIN MyCTE ON Employee.ManagerID = MyCTE.EmpID WHERE Employee.ManagerID不爲NULL) SELECT * FROM MyCTE但這隻給出像經理級別的ID級別而不是相鄰的列 – Nat85

回答

1

下應,起碼讓你在正確的方向前進......

的人誰願意一起玩,我已經出版了tfn_Tally和腳本名字&姓氏表在這裏... 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            
+0

這很好,我可以使用遞歸語句獲得級別/節點。然而,是否有辦法將層級中的所有管理人員顯示爲員工姓名旁邊的多列,從頂層到底層。 – Nat85

+0

是的......這是可行的。一旦我下班,我會在晚上晚些時候更新代碼。 –

+0

@Nataraj - 我的原始答案已更新。 –