2017-09-15 16 views
-2

基本的なSQLクエリについては助けが必要です。列内に階層を構築するためのSQLクエリ

私はSQL Server 2012にテーブルEmpIDManagerIDを持っています。現在のマネージャIDまでEmp IDManager IDManager 1(最高階層)、Manager 2Manager 3というデータを表示するテーブルを作成するクエリを作成したいと思います。

どこから始めたらよいかわからないので、アドバイスをお願いします。

はありがとう

+2

何を研究し、および/または試してみましたか? –

+0

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

+0

私はまったく同じクエリを試しましたマネージャーIDが UNION NULL IS WHERE MyCTE と同じように(従業員 FROMのEmpID、姓、姓、マネージャーID を選択...記事で言及された全ての SELECTのEmpID、姓、姓、マネージャーID 従業員 INNER FROM MyCTE ON Employee.ManagerIDを登録しよう= MyCTE.EmpID ここでEmployee.ManagerIDはNULLではありません) SELECT * FROM MyCTEしかし、これはマネージャレベルのようなIDレベルのみを互いに隣接する列ではありません – Nat85

答えて

1

、最低でも一緒に演奏したい人のため

は、私がtfn_Tallyとのスクリプトを公開した...あなたは正しい方向に進んで取得する必要があり、次のここでの姓& LastNameのテーブル... 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 

EDIT ...名前で分割管理チェーン...(オリジナル#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 - 私の元の回答が更新されました。 –