我有一个表,通过将两个“节点”链接在一起来创建路径。
Node
-----------
Id - Primary Key
Name
etc...
Path
------
Id - Primary Key
From - FK to Node
To - FK to Node
所以这条道路:
W --- X --- Y --- Z
可以这样构建:
Node
Id Name
--- -----
1 W
2 X
3 Y
4 Z
5 A
6 B
7 C
Path
Id From To
--- ------- -------
1 1 2
2 2 3
3 3 4
4 6 7
我已经提出了一个递归CTE查询,它给出了任何Node Id,遍历路径并返回所涉及的所有“路径”。
declare @nodeId = 2
;WITH cte AS (
-- ANCHOR
-- Find one path involving Node
SELECT top 1 p.*, 0 as [Seq] FROM dbo.Path p WHERE [From] = @nodeId or [To] = @nodeId
union all
-- go left
select leftPath.*, cte.[Seq] - 1 as [Seq]
from [Path] leftPath
join cte on cte.[From] = leftPath.[To] and cte.[Seq] <= 0
union all
-- go right
select rightPath.*, cte.[Seq] + 1 as [Seq]
from [Path] rightPath
join cte on cte.[To] = rightPath.[From] and cte.[Seq] >= 0
)
SELECT cte.Id, cte.Seq, cte.From, cte.To
FROM cte
order by [Seq]
所以这会返回所有路径 -
Path
Id Seq From To
--- --- ------- -------
1 -1 1 2
2 0 2 3
3 1 3 4
但是如何编写一个给定其中一个Node Ids的查询,遍历左右路径并返回所涉及的所有DISTINCT(有序)节点?
Id Name
--- -----
1 W
2 X
3 Y
4 Z
答案 0 :(得分:0)
我所说的是:
DECLARE @nodeId int = 2;
select
*
from Node t1
inner join Path t2
on t1.Id = t2.[From] or t1.Id = t2.[To]
where t1.Id = @nodeId
order by t1.Id
我知道,上面的查询并没有解决你的问题但是,使用这个查询你得到的结果与cte相同,而且更简单。从此查询中,如果查询尚未执行,那么您期望的结果是什么。
但我明白这不是你想要的。为此,我需要一个你想要的结果的complet示例,我读到的最后一个段是表节点。 ¿?
答案 1 :(得分:0)
这会返回您想要的结果,但对于@nodeId int = 5;
的情况,它不会返回任何内容,因为没有与该节点关联的路径。
请参阅我从Name's
获取cte.[From]
,然后从 last ID {{1}添加另一个Name
}
我添加了一个来源,以确保订单是您在输出中显示的顺序。否则因为最后两个属于同一行的cte.[To]
可能具有反转顺序。
<强> SQL DEMO 强>
Name's
<强>输出强>
;WITH cte AS (
-- ANCHOR
-- Find one path involving Node
SELECT top 1 p.*, 0 as [Seq] FROM dbo.Path p WHERE [From] = @nodeId or [To] = @nodeId order by [From] desc
union all
-- go left
select leftPath.*, cte.[Seq] - 1 as [Seq]
from [Path] leftPath
join cte on cte.[From] = leftPath.[To] and cte.[Seq] <= 0
union all
-- go right
select rightPath.*, cte.[Seq] + 1 as [Seq]
from [Path] rightPath
join cte on cte.[To] = rightPath.[From] and cte.[Seq] >= 0
)
SELECT 'A' as [Source], cte.Id, cte.Seq, cte.[From], cte.[To], Node.[Name]
FROM cte
JOIN Node
ON cte.[From] = Node.[Id]
UNION
SELECT 'B' as [Source], cte.Id, cte.Seq, cte.[From], cte.[To], Node.[Name]
FROM cte
JOIN Node
ON cte.[To] = Node.[Id]
WHERE cte.id = (SELECT Max(Id) FROM cte)
order by [Source], [Seq]
@nodeId int = 1 to 4 same result:
如果您将上一个查询也放在CTE中并调用@nodeId int = 6 to 7 same result:
,您可以按照以下格式设置:
step2
最终输出