我需要使用遞歸CTE迭代帶有循環的圖。循環的遞歸CTE停止條件
問題是迴路部分。
我想要如果有循環,然後選擇最短的路徑。 這基本上意味着忽略循環,因爲遞歸是「寬度優先」。
下面的示例顯示了返回的數據:
的問題是註釋掉INSERT
語句創建了一個循環。 顯然,它沒有註釋,查詢將永遠不會結束。
我需要的是返回與沒有循環相同的數據。
DROP TABLE IF EXISTS edges;
CREATE TABLE edges(
src integer,
dst integer,
data integer
);
INSERT INTO edges VALUES (1, 2, 1);
INSERT INTO edges VALUES (2, 3, 1);
--INSERT INTO edges VALUES (3, 2, 1); -- This entry creates a loop
INSERT INTO edges VALUES (1, 4, 1);
INSERT INTO edges VALUES (4, 5, 1);
INSERT INTO edges VALUES (5, 2, 1);
INSERT INTO edges VALUES (1, 4, 2);
INSERT INTO edges VALUES (4, 5, 2);
INSERT INTO edges VALUES (4, 6, 2);
WITH RECURSIVE paths AS (
-- For simplicity assume node 1 is the start
-- we'll have two starting nodes for data = 1 and 2
SELECT DISTINCT
src as node
, data as data
, 0 as depth
, src::text as path
FROM edges
WHERE
src = 1
UNION ALL
SELECT DISTINCT
edges.dst
, edges.data
, depth + 1
, paths.path || '->' || edges.dst::text
FROM paths
JOIN edges ON edges.src = paths.node AND edges.data = paths.data
-- AND eliminate loops?
)
SELECT * FROM paths;
返回:
node | data | depth | path
------+------+-------+---------------
1 | 1 | 0 | 1
1 | 2 | 0 | 1
2 | 1 | 1 | 1->2
4 | 1 | 1 | 1->4
4 | 2 | 1 | 1->4
3 | 1 | 2 | 1->2->3
5 | 2 | 2 | 1->4->5
6 | 2 | 2 | 1->4->6
5 | 1 | 2 | 1->4->5
2 | 1 | 3 | 1->4->5->2
3 | 1 | 4 | 1->4->5->2->3
(11 rows)
帶有遞歸CTE的有向循環圖的最短路徑遍歷。耐人尋味。快速搜索找到很多關於這個話題寫的... –
感謝您刪除重複的帖子和一個有趣的一個在這裏; +1,如果我得到時間,將與此玩。 –
我已經有了答案(這是非常明顯和簡單的),但不會在這裏提供:)想看其他選項。 –