2010-03-02 20 views
5

Data la seguente query ricorsiva:ricorsivo Query - Solo selezionare nodi in cui i nodi foglia rappresentano i dati attivi

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 

sono in grado di selezionare i dati che assomiglia a questo:

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 

Inoltre, assumere una tabella esiste con DepartmentId e ItemId (es: DepartmentItemRelationship). I nodi foglia della gerarchia dipartimentale sono accoppiati con gli elementi qui.

voglio che il mio query ricorsive ai nodi di ritorno solo (a qualsiasi livello) che hanno almeno un nodo foglia sotto di loro con una corrispondenza nella tabella rapporto reparto/item. Questi nodi potrebbero essere 6 o 7 livelli verso il basso, quindi non sono sicuro di come avrei modificare la mia domanda per essere sicuri di includere quelli.

Grazie, Kyle

+0

Kyle, se si dispone di un nodo foglia che soddisfa il requisito in un livello 6, si desidera mostrare i 5 reparti sopra quel nodo? –

risposta

3

È possibile creare una colonna percorso che tiene traccia della gerarchia. Quindi è possibile aggiungere solo i nodi bambini che hanno una corrispondenza nella tabella DepartmentItemRelationship. E finalmente prendi solo i nodi che almeno hanno un figlio.

provare qualcosa di simile:

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

Questo funziona brillantemente. Il solo fatto di attraversare l'albero mi aiuterà a risolvere i documenti che devo restituire. (Nota: ho rimosso la clausola 'TOP' dal momento che non è stato permesso in una query ricorsiva). –

1

Se ho capito bene, si desidera che tutti i nodi che sono esattamente un livello al di sopra del livello foglia?

In realtà non c'è bisogno di una query ricorsiva per questo. Tutto quello che devi prima è trovare i nodi foglia, quindi selezionare tutti i genitori.

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 

L'unica cosa che questo non ti dirà è il livello. Non sono sicuro di quanto tu ne abbia bisogno. Se non lo fai, questo dovrebbe funzionare meglio della versione ricorsiva; se lo fai, sembra che la domanda di Jose sia OK per questo (a giudicare da una rapida occhiata).

+0

Grazie per il suggerimento, ho accettato l'altra risposta perché mi ha permesso di ottenere dati da tutti i nodi. Apprezzo ancora (e upvoted) la tua risposta. –

Problemi correlati