2009-06-30 94 views
1

表1有一個項目列表。 表2列出了這些項目可以關聯的組。 表3是1和2之間的交叉參考。使用T-SQL過濾分層數據的最佳方法?

表2中的組以層級方式設置。

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

我希望能夠從Table3篩選Table3選擇。
從Table1中選擇項目其中Table3.ParentKey不是'2'或它的任何後代

從其他職位here on stackoverflow我已經能夠使用CTE來識別層次結構。

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 

我想這實際上是一個兩部分問題。

  1. 如何過濾上述內容?例如,返回TopGroup1不在譜系中的所有組。
  2. 我將如何應用它來過濾交叉引用table1中的結果。

回答

1

試試這個

-- 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

這裏有一整本書關於這個主題,請參閱:「Joe Celko's Trees and Hierarchies in SQL for Smarties

個人而言,當我不得不解決這個問題,我使用了一個臨時表來展開層次,然後從臨時選擇的東西表。本質上,您可以在單個查詢中在臨時表中構建另一個圖層,通常層次結構只有5-10層深度,因此您可以在5到10個查詢中展開它。

相關問題