我有一个查询,可以获得两点之间的路径:
with nodes (node) as (
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
),
connected_nodes (node_1,node_2 ) as
(
select 'A','B' from dual union all
select 'B','C' from dual union all
select 'B','D' from dual union all
select 'A','C' from dual union all
select 'A','D' from dual union all
select 'D','C' from dual union all
select 'C','D' from dual
)
select ltrim(sys_connect_by_path(node_1, '->'), '->') as path,
level -1 as hops
from
(
select node as node_1, node_2
from nodes
left join connected_nodes
on(node = node_1)
)
where node_1 = 'C'
connect by nocycle prior node_2 = node_1
and prior node_1 is not null
start with node_1 = 'A'
它工作得很好所以如果我需要从A到C获得路径,它会给出:
PATH HOPS
---------- ----------
A->B->C 2
A->B->D->C 3
A->C 1
A->D->C 2
我需要的是让路径互惠,这意味着从A到C的过程与从C到A的过程相同,但在上面的查询中并非如此,就像我请求路径一样从C到A,它不会返回数据。
您可以帮我调整查询以满足我的需求吗?
答案 0 :(得分:1)
要获得相反的路径,你需要以另一种方式走树;我不认为你可以在一个分层查询中做到这一点,而不会引入一些奇怪的转移。
您可以将搜索方向联合起来:
with connected_nodes (node_1,node_2 ) as
(
select 'A','B' from dual union all
select 'B','C' from dual union all
select 'B','D' from dual union all
select 'A','C' from dual union all
select 'A','D' from dual union all
select 'D','C' from dual union all
select 'C','D' from dual
)
select ltrim(sys_connect_by_path(node_1, '->'), '->') as path,
level -1 as hops
from connected_nodes
where node_1 = 'C'
connect by nocycle prior node_2 = node_1
and prior node_1 is not null
start with node_1 = 'A'
union all
select ltrim(sys_connect_by_path(node_1, '->'), '->') as path,
level -1 as hops
from connected_nodes
where node_1 = 'C'
connect by nocycle prior node_1 = node_2
and prior node_2 is not null
start with node_1 = 'A'
/
对于您的初始条件仍会得到相同的结果:
PATH HOPS
-------------------------------------------------- ----------
A->B->C 2
A->B->D->C 3
A->C 1
A->D->C 2
但是所有引用A
和C
的反转都会产生反向路径:
with connected_nodes (node_1,node_2 ) as
(
select 'A','B' from dual union all
select 'B','C' from dual union all
select 'B','D' from dual union all
select 'A','C' from dual union all
select 'A','D' from dual union all
select 'D','C' from dual union all
select 'C','D' from dual
)
select ltrim(sys_connect_by_path(node_1, '->'), '->') as path,
level -1 as hops
from connected_nodes
where node_1 = 'A'
connect by nocycle prior node_2 = node_1
and prior node_1 is not null
start with node_1 = 'C'
union all
select ltrim(sys_connect_by_path(node_1, '->'), '->') as path,
level -1 as hops
from connected_nodes
where node_1 = 'A'
connect by nocycle prior node_1 = node_2
and prior node_2 is not null
start with node_1 = 'C'
/
PATH HOPS
-------------------------------------------------- ----------
C->A 1
C->B->A 2
C->D->A 2
C->D->B->A 3
您不需要内联视图,或直接引用node
表,至少需要您的示例数据。联合的第一个分支在一个方向上进行分层查询;第二个分支转向另一个方向,交换prior
和not null
检查中的引用。一个分支总是没有行,另一个分支得到你想要的路径;开始/结束条件决定哪个分支得到哪个。
答案 1 :(得分:1)
如果您有双向图表,请使用UNION ALL
在查询中同时包含node_1, node_2
和反向node_2, node_1
:
with connected_nodes (node_1,node_2 ) as
(
select 'A','B' from dual union all
select 'B','C' from dual union all
select 'B','D' from dual union all
select 'A','C' from dual union all
select 'A','D' from dual union all
select 'D','C' from dual union all
select 'C','D' from dual
)
select SUBSTR(sys_connect_by_path(node_2, '->'), 3) as path,
level -1 as hops
from ( SELECT node_1, node_2 FROM connected_nodes
UNION ALL
SELECT node_2, node_1 FROM connected_nodes
UNION ALL
SELECT null, 'C' FROM DUAL -- Fake connection to start vertex which
-- prevents C being revisited with the
-- NOCYCLE keyword.
)
where node_2 = 'A'
start with node_1 IS null
connect by nocycle prior node_2 = node_1;
<强>输出强>:
PATH HOPS
----------- ----
C->A 1
C->B->A 2
C->B->D->A 3
C->D->A 2
C->D->B->A 3
C->D->A 2
C->D->B->A 3