2017-05-14 5 views
0

Ich muss eine Abfrage erstellen, die die Mitarbeiter, den Manager, Active und die aktiven Nachkommen unter der Hierarchie des Managers anzeigt. Jeder kann mir dabei helfen?So erhalten Sie die Anzahl aktiver Abkömmlinge des Managers

Ergebnisse:

/* EmployeeId ManagerId IsActive NoofDescendantsActive 
    1   -1  0    4     
    2   1  1    3 
    3   1  0    2 
    4   2  1    2 
    6   2  0    0 
    7   3  1    0 
    8   3  1    0 
    9   4  1    1 
    10   9  1    0 
    11   9  0    0 

*/

create table Person 
(
    EmployeeId int, 
    ManagerId int, 
    IsActive bit 
); 

insert into Person(EmployeeId,ManagerId,IsActive) values 
(1, -1, 0), 
(2, 1, 1), 
(3, 1, 0), 
(4, 2, 1), 
(6, 2, 0), 
(7, 3, 1), 
(8, 3, 1), 
(9, 4, 1), 
(10, 9, 1), 
(11, 9, 0); 
+0

Giv e Ihre erwartete Ausgabe – Utsav

+1

@cris gomez - Wie berechnen Sie aktive Nachkommen? Employee ID # 1 scheint 1 aktives direktes Descendend, aber 6 aktive aktive Nachkommen zu haben. Du fragst dich, wie du 3 bekommst? –

+0

@DL, unter der ID # 1 Hierarchie, ist ID # 2 (aktiv) und ID # 3 (nicht aktiv) basiert auf IsActive Feld, unter ID # 2, ist ID # 4 (aktiv) und ID # 6 (nicht aktiv), ID # 3 hat keine Nachkommen, Unter ID # 4 ist ID # 9 (aktiv), Unter ID # 9 ist ID # 10 (aktiv) und ID # 11 (nicht aktiv). Da wir die aktiven Nachkommen erhalten, erhalten wir nur 3 Nein von aktiven Nachkommen. Wenn Sie weitere Informationen benötigen, senden Sie uns einfach eine Nachricht. Danke –

Antwort

2

Die solution von Giorgos hat einen Fehler. Wenn Mitarbeiter # 6 made active ist, sollte Manager # 1 nur um 1 erhöht werden. Doch in seiner Lösung, sie um 2 erhöht

EmployeeId NoofDescendantsActive 
1   6 
2   4 
3   2 
4   2 
9   1 

Hier ist eine Lösung, die funktioniert:

with Managers as 
(
    select 
     RootManagerId = EmployeeId, IsActive 
    from dbo.Person 
    where EmployeeId in (select ManagerId from dbo.Person where IsActive = 1)  
), 
A as -- Manager with employees 
(
    select m.RootManagerId, AnchorManagerId = m.RootManagerId, 
      ManagerId = convert(int, null) 
    from Managers m 

    union all 

    select m.RootManagerId, AnchorManagerId = d.EmployeeId, 
      d.ManagerId 
    from A m 
    -- collect descendants 
    join dbo.Person d on m.AnchorManagerId = d.ManagerId and d.IsActive = 1 
), 
Solution as 
(
    select RootManagerId, count(*) as Descendants 
    from A 
    where ManagerId is not null 
    group by RootManagerId 
) 
-- select * from A order by RootManagerId; -- Uncomment to see how things works 
select * from Solution; 

Result:

RootManagerId Descendants 
1    4 
2    3 
3    2 
4    2 
9    1 

Hier ist die result wenn Mitarbeiter # 6 aktiviert wird :

RootManagerId Descendants 
1    5 
2    4 
3    2 
4    2 
9    1 
2

Ich glaube, Sie das gewünschte Ergebnis kann die folgende rekursiven CTE mit:

;WITH Descendants_CTE AS (
    -- Anchor member: Get leaf nodes first 
    SELECT p1.EmployeeId, p1.ManagerId, p1.IsActive, 0 AS level 
    FROM Person AS p1 
    WHERE NOT EXISTS (SELECT 1 
         FROM Person AS p2 
         WHERE p2.ManagerId = p1.EmployeeId) 

    UNION ALL 

    -- Recursive member: Get nodes of next level, keep track of 
    -- the number of active nodes so far 
    SELECT p.EmployeeId, p.ManagerId, p.IsActive, level = level + 1 
    FROM Person AS p 
    INNER JOIN Descendants_CTE AS d ON p.EmployeeId = d.ManagerId 
    WHERE d.IsActive = 1   
) 
SELECT EmployeeId, SUM(level) AS NoofDescendantsActive 
FROM Descendants_CTE 
WHERE level > 0 
GROUP BY EmployeeId 

Die Rekursion den Baum durchquert 'bottom-up', addiere die Anzahl der 'aktiven' Knoten mich t so weit. Wenn ein nicht aktiver Knoten erfüllt ist, wird die Traversierung beendet. Mit einem GROUP BY können wir die Gesamtzahl der aktiven Knoten unter jedem Nicht-Blatt-Knoten erhalten. Wenn Sie die zusätzlichen Felder auch erhalten möchten, dann müssen Sie die obige Abfrage an die ursprüngliche Tabelle JOIN senden.

Hinweis: Um besser zu verstehen, wie der Algorithmus der Abfrage tatsächlich funktioniert, können Sie ein Diagramm des Baums auf einem Stück Papier erstellen. Markieren Sie jeden aktiven Knoten mit einem farbigen Marker.

Demo here

+0

Danke Giorgos Betsos. :) –

+0

@crisgomez Ich bin froh, dass ich helfen konnte. Bitte markieren Sie diese oder eine andere Antwort als akzeptiert, wenn sie Ihnen bei der Lösung Ihres Problems geholfen hat. –

Verwandte Themen