使用T-SQL过滤分层数据的最佳方法?

时间:2009-06-30 21:36:36

标签: sql database tsql

Table1有一个项目列表。 表2列出了与项目相关联的组。 表3是1和2之间的交叉引用。

表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中选择Table1 从Table1中选择项目Table3.ParentKey NOT'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. 我如何将其应用于过滤引用表1中的结果。

2 个答案:

答案 0 :(得分:2)

有关于此主题的整本书,请参阅:“Joe Celko's Trees and Hierarchies in SQL for Smarties

就个人而言,当我不得不解决这个问题时,我使用了临时表来展开层次结构,然后从临时表中选择了一些东西。基本上,您可以在单个查询中在临时表中构建另一个层,通常层次结构只有5到10层深,因此您可以在5到10个查询中展开它。

答案 1 :(得分: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
                 )