我有一个输入数据,包括ID,prev,current和next节点(未排序)
我必须在每个ID的第一页和最后一页之间找到一条路径,它覆盖了所有遍历的节点
例如:如果我的输入数据如下:
第一列是ID,第二列是prev_node,第三列是当前节点,第四列是下一个节点
对于起始值,Prev_node将为空,而对于最后一个值
输入
id prev current next
------------------------
1 a b c
1 a e f
1 a b g
1 a b o
1 b c d
1 b g h
1 b o p
1 c d a
1 c b g
1 d a e
1 e f e
1 e f f
1 f e f
1 f f f
1 f f a
1 f a b
1 g h i
1 h i j
1 h j i
1 i j i
1 i i k
1 i k l
1 j i i
1 k l m
1 l m n
1 l n a
1 m n a
1 n a b
1 o p q
1 p q r
1 q r s
1 r s t
1 s t u
1 t u v
1 u v w
1 v w x
1 w x
1 a b
输出应该是当前节点的路径,如 -
ID current
-------------
1 a
1 b
1 c
1 d
1 a
1 e
1 f
1 e
1 f
1 f
1 f
1 a
1 b
1 b
1 g
1 h
1 i
1 j
1 j
1 i
1 i
1 k
1 l
1 m
1 n
1 n
1 a
1 b
1 o
1 p
1 q
1 r
1 s
1 t
1 u
1 v
1 w
1 x
这里会有许多ID类似的ID。我只显示了一个ID(1)。另外在这里我使用的字母实际上是200-500个字符长的字符串。我尝试了几乎没有修改的SQL方法,如果一个ID有100行或者以下的行,它可以正常工作,但是对于更多行(即使将长字符串转换为数字后)也会产生字符串连接错误。任何人都可以建议一个强大的基于过程的方法相同。我尝试了一些,但它不适用于超过300行的ID。
答案 0 :(得分:0)
with
t_n as (
select prev, curr, next, rownum n from your_table
),
t_br as (
select prev, curr,
'<'||listagg(n, '|<')within group(order by n)||'|' br,
count(0) cnt
from t_n
group by prev, curr
),
t_mp as (
select
'|'||listagg(list)within group(order by null) list
from (
select replace(br, '<') list
from t_br
where cnt > 1
)
),
t_path(step, curr, next, used) as (
select 1, curr, next, ''
from t_n where prev is null
union all
select step + 1, t_br.curr, t_n.next,
case when instr(list, '|'||n||'|') = 0 then used
else used||n||'|' end
from t_mp, t_path
join t_br
on next = t_br.curr and t_path.curr = prev
join t_n
on n = regexp_substr(br,'^(<('||used||'0)\|)*(<(\d+))?',1,1,'',4)
) cycle step set is_cycle to 'Y' default 'N'
select step, curr from t_path order by 1;