这个select语句会产生奇怪的结果:
with data(id, seqno, cs_prev_seqno, descr) as
(select 1, 1, 0, 'Id 1 Step1' from dual
union all
select 1, 2, 1, 'Id 1 Step2' from dual
union all
select 1, 3, 2, 'Id 1 Step3' from dual
union all
select 1, 4, 1, 'Id 1 Step4' from dual
union all
select 2, 1, 0, 'Id 2 Step1' from dual
union all
select 2, 2, 1, 'Id 2 Step2' from dual)
select id,
sys_connect_by_path(seqno, '/') as path,
seqno,
cs_prev_seqno,
descr,
level
from data
where id = 1
connect by prior seqno = cs_prev_seqno
start with cs_prev_seqno = 0;
我预计connect by
仅针对id = 1的行完成,但结果为:
id path seq seq_prev descr level
1 /1 1 0 Id 1 Step1 1
1 /1/2 2 1 Id 1 Step2 2
1 /1/2/3 3 2 Id 1 Step3 3
1 /1/2/3 3 2 Id 1 Step3 3
1 /1/4 4 1 Id 1 Step4 2
1 /1/2 2 1 Id 1 Step2 2
1 /1/2/3 3 2 Id 1 Step3 3
1 /1/2/3 3 2 Id 1 Step3 3
1 /1/4 4 1 Id 1 Step4 2
即。首先,对所有行执行connect by
,然后按id过滤结果。
作为解决方法,以下语句提供了正确的结果:
with data(id,
seqno,
cs_prev_seqno,
descr) as
(select 1, 1, 0, 'Id 1 Step1'
from dual
union all
select 1, 2, 1, 'Id 1 Step2'
from dual
union all
select 1, 3, 2, 'Id 1 Step3'
from dual
union all
select 1, 4, 1, 'Id 1 Step4'
from dual
union all
select 2, 1, 0, 'Id 2 Step1'
from dual
union all
select 2, 2, 1, 'Id 2 Step2'
from dual
)
,
data2 as
(select d.id,
d.seqno,
d.cs_prev_seqno,
d.id || '.' || d.seqno as id_seqno,
d.id || '.' || d.cs_prev_seqno as cs_id_prev_seqno,
d.descr
from data d)
select id,
sys_connect_by_path(seqno, '/') as path,
seqno,
cs_prev_seqno,
descr,
level
from data2
where id = 1
connect by prior id_seqno = cs_id_prev_seqno
start with cs_prev_seqno = 0;
- >
id path seq seq_prev descr level
1 /1 1 0 Id 1 Step1 1
1 /1/2 2 1 Id 1 Step2 2
1 /1/2/3 3 2 Id 1 Step3 3
1 /1/4 4 1 Id 1 Step4 2
但我想应该有更简单的方法来实现这一目标?提前谢谢!
答案 0 :(得分:2)
使用CONNECT BY
限制与同一ID
的连接:
CONNECT BY PRIOR id = id
AND PRIOR seqno = cs_id_prev_seqno
哪会使您的查询:
SELECT id,
SYS_CONNECT_BY_PATH(seqno, '/') AS path,
seqno,
cs_prev_seqno,
descr,
level
FROM data d
WHERE id = 1
CONNECT BY PRIOR id = id
AND PRIOR seqno = cs_id_prev_seqno
START WITH cs_prev_seqno = 0;
我预计
的行完成connect by
仅针对id = 1
正如你所知,这不是真的。查询将找到以下所有行:
cs_prev_seqno = 0
(根据START WITH
子句); id = 1
(WHERE
子句);和CONNECT BY
子句得到满足。如果CONNECT BY
子句未指定ID
应该是常量,则不会检查这些干预步骤。
答案 1 :(得分:1)
如果我理解得很清楚,您可以在应用CONNECT BY
之前尝试限制数据集,例如:
with data(id, seqno, cs_prev_seqno, descr) as
(select 1, 1, 0, 'Id 1 Step1' from dual union all
select 1, 2, 1, 'Id 1 Step2' from dual union all
select 1, 3, 2, 'Id 1 Step3' from dual union all
select 1, 4, 1, 'Id 1 Step4' from dual union all
select 2, 1, 0, 'Id 2 Step1' from dual union all
select 2, 2, 1, 'Id 2 Step2' from dual)
select id,
sys_connect_by_path(seqno, '/') as path,
seqno,
cs_prev_seqno,
descr,
level
from ( select * from data where id = 1)
connect by prior seqno = cs_prev_seqno
start with cs_prev_seqno = 0;
您甚至可以在CONNECT BY
子句中使用您的条件:
with data(id, seqno, cs_prev_seqno, descr) as
(select 1, 1, 0, 'Id 1 Step1' from dual union all
select 1, 2, 1, 'Id 1 Step2' from dual union all
select 1, 3, 2, 'Id 1 Step3' from dual union all
select 1, 4, 1, 'Id 1 Step4' from dual union all
select 2, 1, 0, 'Id 2 Step1' from dual union all
select 2, 2, 1, 'Id 2 Step2' from dual)
select id,
sys_connect_by_path(seqno, '/') as path,
seqno,
cs_prev_seqno,
descr,
level
from data where id = 1
connect by prior seqno = cs_prev_seqno
and prior id = 1
start with cs_prev_seqno = 0;