2016-09-11 4 views
2

Ich habe Baumstruktur in Tabelle Mitarbeiter (ID, Name, ParentID) und diese Tabelle kann verschachtelt sein. Mitarbeiter ist 1: n-Beziehung zu einer anderen Tabelle Verkäufe mit Spalten (ID , MitarbeiterID, Menge). Jeder Mitarbeiter hat Verkaufsmenge. Ich möchte die Summe der Quantität für jeden Angestellten zusammen mit Kinderangestellten berechnen. Ich habe etwas Code geschrieben, um klarer zu sein.Berechnen Summe der Werte im Baum (rekursive Abfrage)

DECLARE @Employees TABLE(ID INT, Name NVARCHAR(100), ParentID INT); 
DECLARE @Sales TABLE(ID INT, EmployeeID INT, Quantity INT);  

INSERT INTO @Employees(ID, Name, ParentID)VALUES 
(1,N'Employee1', NULL), 
(2,N'Employee2', 1), 
(3,N'Employee3', 2), 
(4,N'Employee4', NULL), 
(5,N'Employee5', 4), 
(6, N'Employee6', 5) 

INSERT INTO @Sales(ID, EmployeeID, Quantity)VALUES 
(1,1,4), 
(2,1,2), 
(3,2,3), 
(4,3,2), 
(5,3,7), 
(6,5,8), 
(7,5,3), 
(8,6,2) 

trat ich diese Tabellen und sieht mag dies:

enter image description here

Hier ist meine Abfrage

;WITH cte 
AS 
(
    SELECT e.ID, e.Name, e.ParentID FROM @Employees e 
    WHERE e.ParentID IS NULL 
    UNION ALL 
    SELECT e.ID, e.Name, e.ParentID FROM @Employees e 
    INNER JOIN cte c ON c.ID = e.ParentID 
) 
SELECT 
    c.ID 
    ,c.Name 
    ,c.ParentID 
    ,ISNULL(SUM(s.Quantity), 0) AS ParentSumSales 
    ,ISNULL(LEAD(SUM(s.Quantity)) OVER(ORDER BY c.ID), 0) AS ChildSumSales 
FROM cte c 
    LEFT JOIN @Sales s ON s.EmployeeID = c.ID 
GROUP BY c.ID, c.Name, c.ParentID 

Abfrage dieses Ergebnis zurückgibt:
enter image description here

Aber diese ich nicht richtig s, möchte ich wie diese Daten erhalten:

ID  Name  ParentSumSales ChildSumSales 
--- --------- -------------  ------------- 
1  Employee1 6     12 
2  Employee2 3     9 
3  Employee3 9     0 
4  Employee4 0     13 
5  Employee5 11    2 
6  Employee6 2     0 

Antwort

1

Ihr Versuch, LEAD zu verwenden, funktioniert nicht, da nicht alle vorherigen Ebenen summiert werden und die IDs müssen fortlaufend sein.

Explode die volle Hierachie für jeden Mitarbeiter zuerst, so dass jede employe einmal pro Hierarchieebene enthalten ist:

;WITH cte 
AS 
(
    SELECT e.ID, e.Name, e.ID as sub_ID 
    FROM @Employees e 
    -- no WHERE-condition to get all employees 
    UNION ALL 
    SELECT 
    c.ID, c.Name -- keep the initial employee 
    ,e.ID as sub_ID 
    FROM @Employees e 
    INNER JOIN cte c ON c.sub_ID = e.ParentID 
) 

SELECT 
    c.ID 
    ,c.Name 
    -- parent level 
    ,sum(case when c.id = s.EmployeeID then s.Quantity else 0 end) AS ParentSumSales 
    -- child level 
    ,sum(case when c.id <> s.EmployeeID then s.Quantity else 0 end) AS ChildSumSales 
FROM cte c 
LEFT JOIN @Sales as s 
ON s.EmployeeID = c.sub_ID 
group by c.Name, c.id 
+0

ja, es funktioniert, danke, aber von innen kommen links gibt es keine Notwendigkeit Gruppe und Summe zu verwenden ist es funktioniert auch ohne es – www1986

+0

@ www1986: Dies war ein Rest von versuchen, Ihre ursprüngliche Abfrage zu beheben und ich habe es nicht überprüft :) Ich werde meine Antwort entsprechend ändern – dnoeth

1

Wenn Ihre „Mitarbeiter“ Tabelle gelegentlich ändert, empfehle ich Ihnen Nested set model zu implementieren. Das Schreiben wird komplexer, aber das Lesen wird einfacher und schneller.