2010-03-02 22 views
5

Angesichts der folgenden rekursiven Abfrage darstellen:rekursive Abfrage - Nur ausgewählte Knoten, an denen Blattknoten aktive Daten

WITH DepartmentHierarchy (DepartmentID, Name, IsInactive, IsSpecial, ParentId, HierarchyLevel) AS 
(
    -- Base case 
    SELECT 
     DepartmentId, 
     Name, 
     IsInactive, 
     IsSpecial, 
     ParentId, 
     1 as HierarchyLevel 
    FROM StoreDepartment 
    WHERE ParentId IS NULL 

    UNION ALL 

    -- Recursive step 
    SELECT 
     d.DepartmentId, 
     d.Name, 
     d.IsInactive, 
     d.IsSpecial, 
     d.ParentId, 
     dh.HierarchyLevel + 1 AS HierarchyLevel 
    FROM StoreDepartment d 
     INNER JOIN DepartmentHierarchy dh ON 
     d.ParentId = dh.DepartmentId 
) SELECT * FROM DepartmentHierarchy 

Ich bin in der Lage, Daten auszuwählen, die wie folgt aussieht:

DepartmentId, Name, IsInactive, IsSpecial, ParentId, HeirarchyLevel 
1, Store, 0, 0, NULL, 1 
2, Main Department 1, 0, 1, 2 
3, Main Department 2, 0, 1, 2 
4, Sub For Main 1, 0, 2, 3 

sei auch angenommen, ein Tabelle existiert mit DepartmentId und ItemId (Beispiel: DepartmentItemRelationship). Blattknoten aus der Abteilung Hierarchie werden hier mit Objekten gepaart.

Ich möchte meine rekursive Abfrage nur Knoten (auf jeder Ebene) zurückgeben, die mindestens einen Blattknoten unter ihnen mit einer Übereinstimmung in der Abteilungs/Element-Beziehungstabelle haben. Diese Knoten könnten 6 oder 7 Ebenen tiefer liegen, also bin ich mir nicht sicher, wie ich meine Abfrage ändern würde, um sicher zu sein, dass sie diese enthält.

Danke, Kyle

+0

Kyle, wenn Sie einen Blattknoten haben, der die Anforderung in einer Ebene 6 erfüllt, möchten Sie die 5 Abteilungen über diesem Knoten anzeigen? –

Antwort

3

Sie können einen Pfad Spalte erstellen, die den Überblick über die Hierarchie hält. Dann können Sie nur die untergeordneten Knoten hinzufügen, die eine Übereinstimmung in der Tabelle DepartmentItemRelationship aufweisen. Und schließlich bekommen nur die Knoten, die mindestens ein Kind haben.

versuchen, etwas wie folgt aus:

WITH DepartmentHierarchy (DepartmentID, Name, IsInactive, IsSpecial, ParentId, HierarchyLevel) AS 
(
    -- Base case 
    SELECT 
     '/'+cast(DepartmentId as varchar(max)) as [path] 
     DepartmentId, 
     Name, 
     IsInactive, 
     IsSpecial, 
     ParentId, 
     1 as HierarchyLevel 
    FROM StoreDepartment 
    WHERE ParentId IS NULL 

    UNION ALL 

    -- Recursive step 
    SELECT 
     dh.[path] +'/'+ cast(d.DepartmentId as varchar(max)) as [path] 
     d.DepartmentId, 
     d.Name, 
     d.IsInactive, 
     d.IsSpecial, 
     d.ParentId, 
     dh.HierarchyLevel + 1 AS HierarchyLevel 
    FROM StoreDepartment d 
     INNER JOIN DepartmentHierarchy dh ON 
     d.ParentId = dh.DepartmentId 
    where exists (select top 1 1 
        from DepartmentItemRelationship di 
        where di.DepartmentId = d.DepartmentId) 
) 
SELECT * 
FROM DepartmentHierarchy dh 
where exists (select top 1 1 
       from DepartmentHierarchy 
       where charindex('/'+dh.DepartmentID+'/',[path]) > 0) 
+0

Das funktioniert hervorragend. Wenn ich nur den Pfad der Durchquerung durch den Baum habe, kann ich herausfinden, welche Datensätze ich zurückgeben muss. (Anmerkung: Ich habe die TOP-Klausel entfernt, da sie in einer rekursiven Abfrage nicht erlaubt war). –

1

Wenn ich Sie richtig verstehe, wollen Sie alle Knoten, die genau eine Ebene über der Blattebene sind?

Sie benötigen dazu eigentlich keine rekursive Abfrage. Alles, was Sie tun müssen, ist zuerst die Blattknoten zu finden und dann alle Eltern auszuwählen.

WITH LeafNodeParents AS 
(
    SELECT DISTINCT ParentId 
    FROM StoreDepartment 
    WHERE DepartmentId NOT IN 
    (
     SELECT DISTINCT ParentId FROM StoreDepartment 
    ) 
) 
SELECT d.DepartmentId, d.Name, d.IsInactive, d.IsSpecial, d.ParentId 
FROM LeafNodeParents p 
INNER JOIN StoreDepartment d 
    ON d.DepartmentId = p.ParentId 

Das einzige, was Ihnen das nicht sagen wird, ist das Niveau. Ich bin mir nicht sicher, wie sehr du das brauchst. Wenn Sie dies nicht tun, sollte dies viel besser als die rekursive Version sein; Wenn Sie das tun, sieht es so aus, als wäre Jose's Anfrage OK (nach einem kurzen Blick).

+0

Danke für den Vorschlag, ich habe die andere Antwort akzeptiert, weil es mir erlaubt, Daten von allen Knoten zu erhalten. Ich weiß Ihre Antwort immer noch zu schätzen. –