2016-12-21 4 views
3

Dies ist meine Tabelle:SQL Server Eltern Kind (Eltern alles sehen)?

EmployeeID Employee ManagerID 
--------------------------------- 
    1  Anna   5 
    2  John   4 
    3  Steve   4 
    4  Lisa   1 
    5  Adam   NULL 
    6  Per   1 

Es ist kein Problem für mich mit einem selbst verbinden wie diese Eltern und Kind-Beziehung zu erhalten:

SELECT 
    E.EmployeeID, 
    E.Employee AS Employee, 
    E.ManagerID, 
    M.Employee AS Manager 
FROM 
    Employee AS E 
LEFT JOIN 
    Employee AS M ON E.ManagerID = M.EmployeeID 

EmployeeID Employee ManagerID Manager 
1 Anna 5 Adam 
2 John 4 Lisa 
3 Steve 4 Lisa 
4 Lisa 1 Anna 
5 Adam NULL NULL 
6 Per  1 Anna 

jedoch Wie würde ich machen gehen über zu sicher, dass die Eltern die gesamte Hierarchieebene sehen?

ich die Tabelle wie folgt aussehen würde:

EmployeeID Manager Employee EmployeeID 
5 Adam Anna 1 
5 Adam Per  6 
5 Adam Lisa 4 
5 Adam John 2 
5 Adam Steve 3 
1 Anna Per  6 
1 Anna Lisa 4 
1 Anna John 2 
1 Anna Steve 3 
4 Lisa John 2 
4 Lisa Steve 3 

Hinweis: in diesem Beispiel habe ich nur 3 Stufen der Krippe, aber es kann viel mehr

+2

SQL Server einen hierarchyid Typ für diese hat. –

+1

Ein alternativer Ansatz ist die Verwendung eines [rekursiven CTE] (https://technet.microsoft.com/en-us/library/ms186243%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396). Je nach Anzahl der Datensätze und der Anzahl der Ebenen ist diese Methode möglicherweise etwas langsam. –

+0

Hi, Ja, ich habe mir rekursive CTE angesehen, aber ich habe nicht ganz verstanden, wie man es benutzt, ohne die Ebenen zu kennen. Hast du ein Beispiel für diese Frage, von der ich ausgehen kann? – Nils

Antwort

2

sein Sie können diese versuchen:

DECLARE @DataSource TABLE 
(
    [EmployeeID] TINYINT 
    ,[Employee] VARCHAR(12) 
    ,[ManagerID] TINYINT 
); 

INSERT INTO @DataSource ([EmployeeID], [Employee], [ManagerID]) 
VALUES (1, 'Anna', 5) 
     ,(2, 'John', 4) 
     ,(3, 'Steve', 4) 
     ,(4, 'Lisa', 1) 
     ,(5, 'Adam', NULL) 
     ,(6, 'Per', 1); 

WITH DataSource AS 
(
    SELECT DISTINCT DS1.* 
        ,0 AS [Level] 
        ,DS1.[EmployeeID] AS Parent 
    FROM @DataSource DS1 
    INNER JOIN @DataSource DS2 
     ON DS1.[EmployeeID] = DS2.[ManagerID] 
    UNION ALL 
    SELECT DS2.* 
      ,DS1.[Level] + 1 
      ,DS1.Parent 
    FROM DataSource DS1 
    INNER JOIN @DataSource DS2 
     ON DS1.[EmployeeID] = DS2.[ManagerID] 
) 
SELECT DS1.[EmployeeID] 
     ,DS1.[Employee] AS [Manager] 
     ,DS.[EmployeeID] 
     ,DS.[Employee] 
FROM DataSource DS 
INNER JOIN @DataSource DS1 
    ON DS.[Parent] = DS1.[EmployeeID] 
WHERE DS.[Level] <> 0 
ORDER BY DS.[Parent] DESC; 

enter image description here

Wir verwenden rekursive CTE und es sieht vielleicht eine Art unordentlich und kompliziert aus, wenn Sie diese Syntax zum ersten Mal sehen, aber es ist nichts besonderes.

Wenn Sie rekursive CTE verwenden, führen Sie einige Leistungstests durch, um sicherzustellen, dass es sich um die richtige Technik zur Lösung Ihres Problems handelt.

1

Sie sollten rekursive CTE-Syntax verwenden. In der ersten Iteration (vor UNION ALL) erhalten Sie alle Eltern-Kind-Paare. Im rekursiven Teil (nach UNION ALL) erhalten Sie für jedes Paar das Kind der nächsten Ebene und ersetzen es in das Paar Eltern-Kind anstelle des Kindes, das das Elternteil verlässt.

WITH CTE AS 
(
    SELECT TP.EmployeeID as ManagerId, 
      TP.Employee as Manager, 
      TC.EmployeeID as EmployeeID, 
      TC.Employee as Employee 

      FROM TEmployee as TP 
      JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID) 

      UNION ALL 

    SELECT TP.ManagerId as ManagerId, 
      TP.Manager as Manager, 
      TC.EmployeeID as EmployeeID, 
      TC.Employee as Employee 

      FROM CTE as TP 
      JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID) 
) 
SELECT * FROM CTE Order By ManagerID 

Ergebnis:

+-----------+---------+------------+----------+ 
| ManagerId | Manager | EmployeeID | Employee | 
+-----------+---------+------------+----------+ 
|   1 | Anna |   4 | Lisa  | 
|   1 | Anna |   6 | Per  | 
|   1 | Anna |   2 | John  | 
|   1 | Anna |   3 | Steve | 
|   4 | Lisa |   2 | John  | 
|   4 | Lisa |   3 | Steve | 
|   5 | Adam |   1 | Anna  | 
|   5 | Adam |   4 | Lisa  | 
|   5 | Adam |   6 | Per  | 
|   5 | Adam |   2 | John  | 
|   5 | Adam |   3 | Steve | 
+-----------+---------+------------+----------+ 
+0

Dies ist perfekt, rekursive CTE wirklich hier praktisch, danke. Ich werde Ihre und @gotqn Antworten als richtig markieren, weil er der erste war, der antwortete. Dies ist jedoch eine gute Erklärung. – Nils