Reputation: 1920
I have a MySQL table as defined below:
SELECT * FROM paths
source | destination
1 | 2
1 | 3
2 | 4
4 | 5
3 | 5
I am trying to find the shortest path between 1 and 5 and not sure what SQL query would get that result. This is what I have right now:
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;
I am not sure how I would limit the query above to only find paths that end at 5. Example of what I am looking for:
All paths between 1 to 5:
In this case, the shortest path that I want the query to return is the second option.
Upvotes: 0
Views: 1238
Reputation: 37472
You're not too far away. Just add the paths' lengths in the recursion. Then filter the final result for the destination node and use ORDER BY
the paths' lengths and LIMIT
to get only one shortest path (if there are more than one path with the minimum length one of them is chosen randomly).
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;
One thing you might consider though is loop handling, if there can be loops in the graph. Unless node 5 is in such a loop you'd have an endless recursion.
Upvotes: 2