Sql server 递归CTE返回路径中所有连接的节点
我有一个表,它通过将两个“节点”链接在一起来创建路径Sql server 递归CTE返回路径中所有连接的节点,sql-server,recursion,common-table-expression,Sql Server,Recursion,Common Table Expression,我有一个表,它通过将两个“节点”链接在一起来创建路径 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
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
SELECT ROW_NUMBER() OVER (ORDER BY [Source], [Seq]) as [Id],
Name
FROM step2
我提出了一个递归CTE查询,它给定任何节点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]
但是,如何编写一个查询,在给定一个节点ID的情况下,遍历向左和向右的路径,并返回所有相关的不同(有序)节点
Id Name
--- -----
1 W
2 X
3 Y
4 Z
我想说的是:
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相同,并且更简单。从这个查询中,如果查询还没有完成,您希望得到什么结果
但我知道这不是你想要的。为此,我需要一个完整的示例来说明您想要的结果,我读的最后一段是table节点。是吗?我想说的是:
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相同,并且更简单。从这个查询中,如果查询还没有完成,您希望得到什么结果
但我知道这不是你想要的。为此,我需要一个完整的示例来说明您想要的结果,我读的最后一段是table节点。?这将返回您想要的结果,但对于
@nodeId int=5的情况代码>它不返回任何内容,因为没有与该节点关联的路径
请参见我从cte.[from]
获取名称
,然后从最后一个idcte.[To]
添加另一个名称
我添加了一个源,以确保顺序与输出中显示的顺序一致。否则,因为最后两个名称的
属于同一行,所以可能具有相反的顺序
;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]
如果将上一个查询也放在CTE中,并调用step2
,则可以使用如下格式:
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
SELECT ROW_NUMBER() OVER (ORDER BY [Source], [Seq]) as [Id],
Name
FROM step2
最终输出
这将返回您想要的结果,但对于@nodeId int=5的情况代码>它不返回任何内容,因为没有与该节点关联的路径
请参见我从cte.[from]
获取名称
,然后从最后一个idcte.[To]
添加另一个名称
我添加了一个源,以确保顺序与输出中显示的顺序一致。否则,因为最后两个名称的
属于同一行,所以可能具有相反的顺序
;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]
如果将上一个查询也放在CTE中,并调用step2
,则可以使用如下格式:
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
SELECT ROW_NUMBER() OVER (ORDER BY [Source], [Seq]) as [Id],
Name
FROM step2
最终输出
您的查询似乎不起作用,例如description
不存在。请把这个修好,我来看看修好了没有;请参阅:该查询与您的输出不匹配。非负Seq
有一个问题,您共享一个LIVE
代码,因此当我编辑时更改代码。使用底部的FORK
创建一个单独的版本。是否尝试此操作?Seq其实并不重要,这可能与前1名获取默认订单的方式不同,我在其中添加了一个orderby子句,以便与示例相匹配。它所做的只是对结果进行正确排序您的查询似乎不起作用,例如description
不存在。请把这个修好,我来看看修好了没有;请参阅:该查询与您的输出不匹配。非负Seq
有一个问题,您共享一个LIVE
代码,因此当我编辑时更改代码。使用底部的FORK
创建一个单独的版本。是否尝试此操作?Seq其实并不重要,这可能与前1名获取默认订单的方式不同,我在其中添加了一个orderby子句,以便与示例相匹配。它所做的只是对结果进行正确排序。您是对的,一个更复杂的样本应该select*From Node order by id
也返回所需的输出。更新的问题。添加了3个新节点和一个新路径。现在有两条路径——W-X-Y-Z和B-C。运行我原来的查询宽度nodeid 2会产生与以前相同的结果——整个路径nodeid 2(名为X)都涉及其中。我的查询返回图形的边,我希望它返回顶点。你是对的,一个更复杂的示例应该select*From Node order by id
也返回所需的输出。更新的问题。添加了3个新节点和一个新路径。现在有两条路径——W-X-Y-Z和B-C。运行我原来的查询宽度nodeid 2会产生与以前相同的结果——整个路径nodeid 2(名为X)都涉及其中。我的查询返回图形的边,我希望它返回顶点。