我有一个id和parent_id的表。我已经看到很多关于如何生成树的CTE。但是我似乎无法过滤树,以便从给定任何节点的位置检索完整的树。
给出值
1, NULL
2, 1
3, 2
4, 2
5, NULL
6, 5
7, NULL
如果我按ID过滤任何值1,2,3或4,我应该得到树
1, NULL
2, 1
3, 2
4, 2
为5或6
5, NULL
6, 5
for 7
7, NULL
可以使用CTE实现吗?
答案 0 :(得分:2)
使用一个CTE定位树的根,然后使用第二个CTE来爆炸树结构:
declare @T table (ID int not null, Parent int null)
insert into @T(ID,Parent) values
(1, NULL),
(2, 1 ),
(3, 2 ),
(4, 2 ),
(5, NULL),
(6, 5 ),
(7, NULL)
declare @Node int
set @node = 3
;With Root as (
select t.ID,t.Parent from @T t where t.ID = @Node or t.Parent = @Node
union all
select t.ID,t.Parent
from
Root r
inner join
@t t
on
t.ID = r.Parent
), Tree as (
select ID,Parent from Root where Parent is null
union all
select t.ID,t.Parent
from @T t
inner join
Tree tr
on tr.ID = t.Parent
)
select * from Tree
结果:
ID Parent
----------- -----------
1 NULL
2 1
3 2
4 2
希望你能看到两个CTE如何在相反的方向上工作。
答案 1 :(得分:1)
您可以像这样使用递归CTE。 CTE使用RootId返回所有树,您可以通过其RootId
获取所有树节点DECLARE @SampleData AS TABLE
(
NodeId int,
ParentNodeId int
)
INSERT INTO @SampleData
(
NodeId,
ParentNodeId
)
VALUES
( 1, NULL),
( 2, 1),
( 3, 2),
( 4, 2),
( 5, NULL),
( 6, 5),
( 7, NULL)
DECLARE @NodeId int = 4
-- temp returns all child nodes of rootid (1,5,7)
;WITH temp AS
(
SELECT sd.NodeId, sd.ParentNodeId, sd.NodeId AS RootId
FROM @SampleData sd
WHERE sd.ParentNodeId IS NULL
UNION ALL
SELECT sd.NodeId, sd.ParentNodeId, t.RootId
FROM temp t
INNER JOIN @SampleData sd ON t.NodeId = sd.ParentNodeId
)
SELECT t2.NodeId, t2.ParentNodeId
FROM temp t
INNER JOIN temp t2 ON t2.RootId = t.RootId
WHERE t.NodeId = @NodeId
OPTION (MAXRECURSION 0)