oracle connect by从句中的rownum

在构造数据时,对于单行的基本数据来说,connect by levelconnect by rownum可以说是等效的。比如说下面的两个语句的结果集是一样的。

with tab1 as (
select 'a' id, 2 num from dual
)
select*from tab1
connect by level <= 2
;

with tab1 as (
select 'a' id, 2 num from dual
)
select*from tab1
connect by rownum <= 2
;
IDNUM
a2
a2

但是当基础数据为多条时,rownum会产生不符合预期的结果。

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 4 num from dual
)
select id, num, rownum rn
  from tab1
connect by rownum <= 4
;
IDNUMRN
a21
a22
a23
a24
b45

我明明指定了rownum <= 4,却得到了5条记录,这是怎么回事?

我之后又写了多条测试语句,最终的结论是:层次查询中的rownum与最后结果集中的rownum并不是一个。

在层次查询中,rownum被赋予的是层次查询中返回的结果集的序号。第一个被查询的根节点的rownum就是1,在此基础上,下一条返回的数据为2,以此类推。当查出第四层时,查询结束。至于多出来的第五条数据,可以这样理解:connect语句的结果集由两部分组成,即由start with查询出的根节点与connect查询出的子节点组成。根节点是不受connect从句约束的,所以当rownum <= 4生效后,其他根节点一并归到了结果集中。又由于oracle的层次查询是深度优先的,所以上面的例子中,实际查出的是一颗左斜树。这就是查出4个a和1个b的原因。

用这个语句能更清晰的看出这些特点。

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 2 num from dual union all
select 'c' id, 4 num from dual
)
select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path
  from tab1
connect by rownum <= 4
IDNUMRNPATH
a21—1_a
a22------2_a
a23---------3_a
a24------------4_a
b25—1_b
c46—1_c

在这个语句的基础上加上where rownum <= 4确实也可以只查出4条数据。

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 2 num from dual union all
select 'c' id, 4 num from dual
)
select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path
  from tab1
 where rownum <= 4
connect by rownum <= 4;

这样可以保证只查出四条数据。

但是当语句的条件多一些后
比如这样

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 2 num from dual
)
select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path
  from tab1
connect by rownum <= 6
and level <= 3
;
IDNUMRNPATH
a21—1_a
a22------2_a
a23---------3_a
b24---------3_b
b25------2_b
a26---------3_a
b27—1_b

这是预料之中的结果,但是我实在想不出什么样的功能会用上这种语句…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值