Tôi hiểu điều này, nó sẽ không đi vào vòng lặp vô hạn với bất kỳ loại dữ liệu nào:
--create temp table edges ("from" text, "to" text);
--insert into edges values ('initial_node', 'a'), ('a', 'b'), ('a', 'c'), ('c', 'd');
with recursive graph(points) as (
select array(select distinct "to" from edges where "from" = 'initial_node')
union all
select g.points || e1.p || e2.p
from graph g
left join lateral (
select array(
select distinct "to"
from edges
where "from" =any(g.points) and "to" <>all(g.points) and "to" <> 'initial_node') AS p) e1 on (true)
left join lateral (
select array(
select distinct "from"
from edges
where "to" =any(g.points) and "from" <>all(g.points) and "from" <> 'initial_node') AS p) e2 on (true)
where e1.p <> '{}' OR e2.p <> '{}'
)
select distinct unnest(points)
from graph
order by 1
Truy vấn đệ quy rất hạn chế về những gì có thể được chọn, và vì chúng không cho phép sử dụng kết quả đệ quy bên trong một lựa chọn con, người ta không thể sử dụng NOT IN (chọn * từ đệ quy ở đâu ...). Lưu trữ kết quả trong một mảng, sử dụng LEFT JOIN LATERAL và sử dụng =ANY () và <> ALL () đã giải quyết được vấn đề hóc búa này.