我正在尝试运行图搜索以查找从起点可访问的所有节点,如下所示:
with recursive
nodes_traversed as (
select START_NODE ID
from START_POSITION
union all
select ed.DST_NODE
from EDGES ed
join nodes_traversed NT
on (NT.ID = ed.START_NODE)
and (ed.DST_NODE not in (select ID from nodes_traversed))
)
select distinct * from nodes_traversed
不幸的是,当我尝试运行时,我收到一个错误:
递归CTE成员(nodes_traversed)只能在FROM子句中引用它自己。
然而,“not in select”子句对递归表达式很重要,因为它提供了结束点。 (没有它,你会得到无限的递归。)使用生成计数,就像the accepted answer to this question一样,没有用,因为这是一个高度循环的图。
有没有办法解决这个问题而不必创建一个迭代执行的存储过程?
答案 0 :(得分:2)
这是我使用全局临时表的解决方案,我按级别和临时表的节点进行了有限的递归。 我不确定它如何适用于大量数据。
create procedure get_nodes (
START_NODE integer)
returns (
NODE_ID integer)
as
declare variable C1 integer;
declare variable C2 integer;
begin
/**
create global temporary table id_list(
id integer
);
create index id_list_idx1 ON id_list (id);
*/
delete from id_list;
while ( 1 = 1 ) do
begin
select count(distinct id) from id_list into :c1;
insert into id_list
select id from
(
with recursive nodes_traversed as (
select :START_NODE AS ID , 0 as Lv
from RDB$DATABASE
union all
select ed.DST_NODE , Lv+1
from edges ed
join nodes_traversed NT
on
(NT.ID = ed.START_NODE)
and nt.Lv < 5 -- Max recursion level
and nt.id not in (select id from id_list)
)
select distinct id from nodes_traversed);
select count(distinct id) from id_list into :c2;
if (c1 = c2) then break;
end
for select distinct id from id_list into :node_id do
begin
suspend ;
end
end