两个节点之间的MySQL最短路径

时间:2019-12-27 21:12:51

标签: mysql sql

我有一个如下定义的MySQL表:

SELECT * FROM paths

source | destination
1 | 2
1 | 3
2 | 4
4 | 5
3 | 5

我正在尝试查找1到5之间的最短路径,并且不确定哪个SQL查询会得到该结果。这就是我现在所拥有的:

WITH RECURSIVE cte AS
(
  SELECT destination, CAST(destination AS CHAR(200)) AS path
  FROM paths WHERE source = 1
  UNION ALL
  SELECT c.destination, CONCAT(cte.path, ",", c.destination)
  FROM paths c JOIN cte ON cte.destination=c.source
)
SELECT * FROM cte ORDER BY path;

我不确定如何将上面的查询限制为仅找到以5结尾的路径。

1到5之间的所有路径:

  • (1-> 2),(2-> 4),(4-> 5)
  • (1-> 3),(3-> 5)

在这种情况下,我要查询返回的最短路径是第二个选项。

1 个答案:

答案 0 :(得分:2)

您距离不太远。只需在递归中添加路径的长度即可。然后过滤目标节点的最终结果,并使用ORDER BY路径的长度和LIMIT来获得一条最短的路径(如果有一条以上且具有最小长度的路径,则随机选择其中一条) )。

WITH RECURSIVE
cte
AS
(
SELECT p.destination,
       concat(p.source, '->', p.destination) path,
       1 length
       FROM paths p
       WHERE p.source = 1
UNION ALL
SELECT p.destination,
       concat(c.path, '->', p.destination) path,
       c.length + 1 length
       FROM cte c
            INNER JOIN paths p
                       ON p.source = c.destination
       WHERE c.destination <> 5
)
SELECT c.path
       FROM cte c
       WHERE c.destination = 5
       ORDER BY c.length
       LIMIT 1;

db<>fiddle

您可能要考虑的一件事是循环处理,如果图形中可能存在循环。除非节点5处于这种循环中,否则您将有无限的递归。