[英]Best way to filter hierarchical data using T-SQL?
Table1 has a list of items. 表1列出了项目。 Table2 has a list of groups the items can be associated with.
Table2列出了可以与项目关联的组。 Table3 is a cross-reference between 1 and 2.
表3是1到2之间的交叉引用。
The groups in table 2 are set up in hierarchical fashion. 表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
I want to be able to select from Table1 filtered by Table3. 我希望能够从由Table3过滤的Table1中进行选择。
Select Items from Table1 Where Table3.ParentKey NOT '2' or any of it's descendants . 从Table1中选择项目,其中Table3.ParentKey不是'2' 或其任何后代 。
From another post here on stack overflow I've been able to use CTE to identify the hierarchy. 在堆栈溢出的另一篇文章中,我已经能够使用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
I guess this is really a two part question. 我想这确实是一个两部分的问题。
There is a whole book on this topic, see: ' Joe Celko's Trees and Hierarchies in SQL for Smarties ' 有一本关于该主题的整本书,请参见:' 聪明人的SQL中的Joe Celko的树和层次结构 '
Personally, when I had to solve this problem, I used a temp table to unroll the hierarchy and then selected stuff from the temp table. 就个人而言,当我必须解决此问题时,我使用了一个临时表来展开层次结构,然后从临时表中选择内容。 Essentially you can build up another layer in the temp table in a single query, usually hierarchies are only 5-10 layers deep, so you can unroll it in 5 to 10 queries.
本质上,您可以在单个查询中在临时表中建立另一层,通常层次仅深5-10层,因此您可以在5到10个查询中展开它。
Try this 尝试这个
-- 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
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.