2009-06-30 11 views
1

Le tableau 1 contient une liste d'éléments. Le tableau 2 contient une liste de groupes auxquels les éléments peuvent être associés. Le tableau 3 est une référence croisée entre 1 et 2.La meilleure façon de filtrer les données hiérarchiques en utilisant T-SQL?

Les groupes du tableau 2 sont configurés de façon hiérarchique.

Key ParentKey Name 
1  NULL   TopGroup1 
2  NULL   TopGroup2 
3  1   MiddleGroup1 
4  2   MiddleGroup2 
5  3   NextGroup1 
6  4   NextGroup1 
7  2   MiddleGroup3 

Je veux être en mesure de sélectionner parmi Table1 filtré par Table3.
Sélectionnez les éléments de Table1 où Table3.ParentKey NOT '2' ou l'un de ses descendants.

D'un autre article here on stackoverflow J'ai pu utiliser CTE pour identifier la hiérarchie.

WITH Parent AS 
(
    SELECT 
     table2.Key, 
     cast(table2.Key as varchar(128)) AS Path 
    FROM 
     table2 
    WHERE 
     table2.ParentKey IS NULL 

    UNION ALL 

    SELECT 
     TH.Key, 
     CONVERT(varchar(128), Parent.Path + ',' + CONVERT(varchar(128),TH.Key)) AS Path 
    FROM 
     table2 TH 
    INNER JOIN 
     Parent 
    ON 
     Parent.Key = TH.ParentKey 
) 
SELECT * FROM Parent 

Je suppose que c'est vraiment une question en deux parties.

  1. Comment filtrez-vous ce qui précède? Par exemple, renvoyez tous les groupes dans lesquels TopGroup1 n'est pas dans le lignage.
  2. Comment l'appliquer aux résultats de filtrage dans le tableau croisé1.

Répondre

1

Essayez cette

-- Table1 (ItemKey as PK, rest of the columns) 
-- Table2 (as you defined with Key as PK) 
-- Table3 (ItemKey as FK referencing Table1(ItemKey), 
--   GroupKey as FK referencing Table2(Key)) 

Declare @Exclude int 
Set @Exclude = 2   
;WITH Groups AS  -- returns keys of groups where key is not equal 
(     -- to @Exclude or any of his descendants 
    SELECT t.Key 
    FROM table2 t 
    WHERE t.ParentKey IS NULL 
     and t.Key <> @Exclude 
    UNION ALL 
    SELECT th.Key, 
    FROM table2 th 
    INNER JOIN Groups g ON g.Key = th.ParentKey 
    Where th.Key <> @Exclude 
) 
SELECT t1.* 
    FROM Table1 t1 
WHERE t1.key in (Select t3.ItemKey 
        From table3 t3 
        Inner Join Groups g2 
         on t3.GroupKey = g2.Key 
       ) 
2

Il y a un livre sur ce sujet, voir: « Joe Celko's Trees and Hierarchies in SQL for Smarties »

Personnellement, quand je devais résoudre ce problème, j'utilisé une table temporaire pour déroulez la hiérarchie, puis sélectionné des choses de la température table. Essentiellement, vous pouvez créer une autre couche dans la table temporaire en une seule requête. Généralement, les hiérarchies ont seulement 5 à 10 couches de profondeur, vous pouvez donc la dérouler en 5 à 10 requêtes.

Questions connexes