您可以为此使用递归 CTE。由于您可以有多个路由,因此返回结果集的最简单方法是将其返回为 JSON
- 有两个锚点和两个递归,因为我们可以从 Point1 到 Point2 或 v.v.每个节点
DECLARE @start int = 3;
DECLARE @end int = 10;
WITH cte AS (
SELECT
Point2 = p.PointId2,
p.RidgeId,
Json = (
SELECT p.RidgeId, p.PointId1, p.PointId2
FOR JSON PATH
)
FROM Points p
WHERE p.PointId1 = @start
UNION ALL
SELECT
Point2 = p.PointId1,
p.RidgeId,
Json = (
SELECT p.RidgeId, p.PointId1, p.PointId2
FOR JSON PATH
)
FROM Points p
WHERE p.PointId2 = @start
UNION ALL
SELECT
Point2 = p.PointId2,
p.RidgeId,
Json = JSON_MODIFY(cte.Json, 'append $', JSON_QUERY((
SELECT p.RidgeId, p.PointId1, p.PointId2
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)))
FROM Points p
JOIN cte ON cte.Point2 = p.PointId1
WHERE p.RidgeId <> cte.RidgeId
UNION ALL
SELECT
Point2 = p.PointId1,
p.RidgeId,
Json = JSON_MODIFY(cte.Json, 'append $', JSON_QUERY((
SELECT p.RidgeId, p.PointId1, p.PointId2
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)))
FROM Points p
JOIN cte ON cte.Point2 = p.PointId2
WHERE p.RidgeId <> cte.RidgeId
)
SELECT Json
FROM cte
WHERE cte.Point2 = @end;
| Result |
| [{"RidgeId":7,"PointId1":11,"PointId2":3}, {"RidgeId":6,"PointId1":18,"PointId2":11}, {"RidgeId":4,"PointId1":18,"PointId2":10}] |
db<>fiddle
这不能很好地处理节点中的循环。理想情况下,您应该通过在每个递归部分中分解 JSON 并检查我们不会返回自己来检查是否没有循环