oracle rownum和connect by 扫盲

最近需要实现一个功能:有这样一个数据

count   user_name

2             周

3             吴

实现结果:

user_name


在网上找到了这样的方法:

with t as(
select 2 as count, '周' user_name from dual
union all
select 3,'吴' from dual
)
select * from t,
(select rownum rn from t connect by rownum <= 3) b
where count>=rn


非常有趣,就去了解了rownum和connect by

ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说 rownum 是对符合条件结果的序列号。它总是从1开始排起的。所以你选出的结果不可能没有1,而有其他大于1的值。

ROWNUM是一个序列,是oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类 推。如果你用>,>=,=,between...and这些条件,因为从缓冲区或数据文件中得到的第一条记录的rownum为1,则被删除, 接着取下条,可是它的rownum还是1,又被删除,依次类推,便没有了数据。

rowid 与 rownum 虽都被称为伪列,但它们的存在方式是不一样的,rowid 可以说是物理存在的,表示记录在表空间中的唯一位置ID,在DB中唯一。只要记录没被搬动过,rowid是不变的。rowid 相对于表来说又像表中的一般列,所以以 rowid 为条件就不会有 rownum那些情况发生。
另外还要注意:rownum不能以任何基表的名称作为前缀。


 with  x  as  

    ( select  'aa'  chr,1 pid,4 id  from  dual

    union  all  

    select  'bb'  chr ,2,5 from  dual
/*        union  all  

    select  'cc'  chr ,3,6 from  dual*/)

    select  level ,chr,lpad( ' ' ,( level - 1 )* 5 , '-' )||chr other  from  x     /* start  with  pid= 1  
*/
    connect  by  level<=3
 

第一行和第八行同属第一层级,第二到第四是第二层级,第三是第三层,看下面的图

如果初始行数是n,总层级是m,这棵树总行数函数是:

f(n,1)=n,

f(n,m)=n*f(n,m-1)+n;

总记录数N,level层数M
结果集数:T=∑N^x(x=1...m)
比如,总记录数为3,层数为3
则结果集数:3^1 +3^2 + 3^3 = 3+9+27=39

接下来是细节:

       SELECT [LEVEL] ,column,expression,...

       FROM table_name

       [WHERE where_clause]

       [[START WITH start_condition] [CONNECT BY PRIOR prior_condition]];

 [[START WITH start_condition] 讲的是这棵树从哪里开始;

prior_condition 具体这样:

prior 列名1=列名2

意思是之前一行的列名1=这一行的列名2

也可以这么写  列名1=prior列名2 ;

还有sys_connect_by_path的用法:

sys_connect_by_path( 列名,‘分隔符号’ )

结合例子就明白了:

 with  x  as  

    ( select  'aa'  chr,1 pid,4 id  from  dual

    union  all  

    select  'bb'  chr ,2,1 from  dual)
/*        select  level ,sys_connect_by_path(pid, '/' )  from  x

    start  with  pid= 1  

    connect  by  prior  pid =  id ;*/
     select  level ,ltrim(sys_connect_by_path( id , '/' ),'/')  from x

    start  with  pid= 1  

    connect  by  prior  pid =  id ;


好像看官应该不太容易明白。。。

自己练习吧。

又碰到这样一种情况

with t as(
select 2 as count, '周' user_name from dual
union all
select 3,'吴' from dual
/*union all
select 4,'郑' from dual*\*/
)
select rownum rn,t.user_name,level from t connect by rownum<=10
结果:


我就去找connect by rownum 和level的区别

重点是rownum,connect by rownum,没有其他条件,是直接递归迭代第一行(反复),然后判断rownum条件,不满足条件结束。正是因为
--递归如果没有start with则每行都是根,先第一轮递归,递归到rownum<n不满足后结束,然后其他根肯定不满足,只选出自身一行。
--则剩余其他几行都显示一次
,因为第1行递归结束后,继续其他行,发现都不满足,结束。这个rownum不是select里的rownum
--connect by 1=1就不结束了

--没有start with,没有prior...的迭代,不管是level,还是rownum,每行都是根节点,自身或其它节点是子节点
--区别是connect by level会先深度搜索,也就是根---自身---其他节点
--connect by rownum则是不停迭代自身(第一行),然后判断rownum。。。

真相大白。

又折腾出一种情况:

with t as(
select 2 as count, '周' user_name from dual
union all
select 3,'吴' from dual
union all
select 4,'郑' from dual
)
select rownum rn,t.user_name,level from t 
connect by rownum=3

当rownum=固定值的情况,可以测试不同值,负数、0,1,2,等,结果不同;保底3个,看能否符合rownum情况决定是否会多一行和该位置;

还有加where条件,connect by加多个条件==。



http://www.cnblogs.com/szlbm/p/5806070.html

http://blog.csdn.net/haiross/article/details/17586565

http://blog.csdn.net/leshami/article/details/5616877

http://www.itpub.net/thread-1615513-1-1.html

http://www.itpub.net/forum.php?mod=viewthread&tid=1570306


  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值