我有一个类似的数据库结构
------------------------------------------
NodeId | Parent
-----------------------------------------
1 0
2 0
3 1
4 1
5 2
6 2
7 3
8 3
9 4
10 4
11 5
12 5
13 6
形成像这样的树结构
1
->3
-->7
-->8
->4
-->9
-->10
2
->5
-->11
-->12
->6
-->13
现在用户可以输入任何节点ID
获取
联盟
例如:
如果用户单击节点ID 1,
结果应该是(我可以通过CTE实现)
1 0
3 1
4 1
7 3
8 3
9 4
10 4
但是如果用户单击任何中间节点(如4)
结果应该是
4 1
9 4
10 4
联合(节点根父节点下的所有节点) 节点的根父代4 = 1 所以结果应该是
1 0
3 1
4 1 (Should be excluded as comes under first query)
7 3
8 3
9 4 (Should be excluded as comes under first query)
10 4 (Should be excluded as comes under first query)
这是我到目前为止的代码:
declare @Node int;
Set @node=1
with [CTE] As
(
Select [nodeid], [Parent]
from [NodeTable]
where [nodeid]=@nodeid
union
Select [
from [Nodetable] [NT]
inner join [CTE] on [CTE].[nodeid]=[NT].[Nodeid]
)
Select * from [CTE]
答案 0 :(得分:0)
您可以首先使用第一个RootId
检索指定节点的CTE
,然后使用CTE2
检索所检索的RootId
的所有子节点:
declare @node int;
Set @node=4;
with [CTE] As
(
Select [nodeid] NodeId, [Parent] Parent
from [NodeTable]
where [nodeid]=@node
union all
Select [NT].[nodeid] ni, [NT].[Parent] pi
from [Nodetable] [NT]
inner join [CTE]
on [CTE].Parent=[NT].NodeId
), [CTE2] As
(
Select [nodeid] NodeId, [Parent] Parent
from [NodeTable]
where [nodeid]= (select top 1 NodeId from CTE order by NodeId)
union all
Select [NT].[nodeid] ni, [NT].[Parent] pi
from [Nodetable] [NT]
inner join [CTE2]
on [CTE2].NodeId=[NT].Parent
)
Select * from [CTE2]
order by NodeId
此外,如果要排除节点本身及其子节点,则可以添加CTE3
来检索节点的子节点,并使用除以得到所需的输出:
declare @node int;
Set @node=4;
with [CTE] As
(
Select [nodeid] NodeId, [Parent] Parent
from [NodeTable]
where [nodeid]=@node
union all
Select [NT].[nodeid] ni, [NT].[Parent] pi
from [Nodetable] [NT]
inner join [CTE]
on [CTE].Parent=[NT].NodeId
), [CTE2] As
(
Select [nodeid] NodeId, [Parent] Parent
from [NodeTable]
where [nodeid]= (select top 1 NodeId from CTE order by NodeId)
union all
Select [NT].[nodeid] ni, [NT].[Parent] pi
from [Nodetable] [NT]
inner join [CTE2]
on [CTE2].NodeId=[NT].Parent
), [CTE3] As
(
Select [nodeid] NodeId, [Parent] Parent
from [NodeTable]
where [nodeid]=@node
union all
Select [NT].[nodeid] ni, [NT].[Parent] pi
from [Nodetable] [NT]
inner join [CTE3]
on [CTE3].NodeId = [NT].Parent
)
Select * from [CTE2]
except
Select * from [CTE3]
order by NodeId
答案 1 :(得分:0)
一种方法是使用递归cte,该cte还将保留每次递归的根节点,然后根据所需节点的根查询该cte。
首先,创建并填充示例表:(请在您将来的问题中为我们保存此步骤)
DECLARE @T AS TABLE
(
NodeId int,
Parent int
);
INSERT INTO @T (NodeId, Parent) VALUES
(1 , 0),
(3 , 1),
(7 , 3),
(8 , 3),
(4 , 1),
(9 , 4),
(10, 4),
(2 , 0),
(5 , 2),
(11, 5),
(12, 5),
(6 , 2),
(13, 6);
递归cte:
WITH CTE AS
(
SELECT NodeId, Parent, NodeId As Root
FROM @T
WHERE Parent = 0
UNION ALL
SELECT t.NodeId, t.Parent, Root
FROM @T As t
JOIN CTE
ON t.Parent = CTE.NodeId
)
查询:
SELECT NodeId, Parent
FROM CTE
WHERE Root = (SELECT Root FROM CTE WHERE NodeId = 4)
结果:
NodeId Parent
1 0
3 1
4 1
9 4
10 4
7 3
8 3