需求:
现在有两个表,一个是票号区间段
一个是单个票号
然后怎么找出区间段多出的票号
比如 区间段是1-10
然后现在另一张表的票是
1,2,4,5,6
然后结果是3,7,8,9
分析:
是把1-10范围的值,变成10行,每行是1到9,然后和票据编码关联,关联不上的就是没用过的
主要是这个一行根据字段的范围扩成多行
create table j (id number,one number,two number);
select * from j for update;
create table j2 (id number,one number);
select * from j2 for update;
with temp1 as(
select distinct * from (
select distinct j.*,level as k,level+one-1 as ne from j /*where j.id=2*/ connect by level<= j.two -j.one+1
)
)
select temp1.id,temp1.one,temp1.two,temp1.ne from temp1
left join j2
on j2.id=temp1.id and j2.one=temp1.ne
where j2.one is null
order by temp1.id, temp1.ne
有个问题with子句里面
select distinct j.*,level as k,level+one-1 as ne from j /*where j.id=2*/ connect by level<= j.two -j.one+1
会出现大量重复数据,2行会变成3000行,有跑蹦数据库的风险,
改良如下
加两个 j.ID=PRIOR j.ID PRIOR SYS_GUID() IS NOT NULL 就不会重复了 ,connect by level涉及到父级子级的问题,比如原表两条数据的时候,先connect by level < 10后,两条变成20条,这20条相互乱认父级,就会导致大量数据重复,类似笛卡尔积,如果找不到父级子级,就把每条数据当成子级或者父级,就一直循环重复了,当然原表只有一条数据就不会重复了,如图,每行数据会乱认父级
改成:
select j.*,level as k,level+one-1 as ne from(select j.* from j /*where j.id in(2)*/ ) j connect by j.ID=PRIOR j.ID
and level<= j.two -j.one+1 and PRIOR SYS_GUID() IS NOT NULL)
最终:
with temp1 as(
select distinct * from (
select j.*,level as k,level+one-1 as ne from(select j.* from j /*where j.id in(2)*/ ) j connect by j.ID=PRIOR j.ID
and level<= j.two -j.one+1 and PRIOR SYS_GUID() IS NOT NULL)
)
select temp1.id,temp1.one,temp1.two,temp1.ne from temp1
left join j2
on j2.id=temp1.id and j2.one=temp1.ne
where j2.one is null
order by temp1.id, temp1.ne
小记:
select j.*,level as k,level+one-1 as ne from(select j.* from j /*where j.id in(2)*/ ) j where j.id in(2)
connect by /*j.ID=PRIOR j.ID
and*/ level<= j.two -j.one+1 --and PRIOR SYS_GUID() IS NOT NULL
select j.*,level as k,level+one-1 as ne from(select j.* from j where j.id in(2) ) j connect by /*j.ID=PRIOR j.ID
and*/ level<= j.two -j.one+1 --and PRIOR SYS_GUID() IS NOT NULL
这两个有区别,一个是connect by 后过滤,会有大量重复数据,一个是之前就过滤,没重复数据,重复数据是因为每行数据乱认父级,解决办法就是加加两个 j.ID=PRIOR j.ID PRIOR SYS_GUID() IS NOT NULL 就不会重复了