Decode360's Blog

业精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

  BlogJava :: 首页 :: 新随笔 :: 联系 ::  :: 管理 ::
  302 随笔 :: 26 文章 :: 82 评论 :: 0 Trackbacks
rownum伪劣的相关问题
 
 
1、在SQL中使用rownum的限制:
 

    select * from t1 where rownum >= 1 ;

    select * from t1 where rownum >= 2 ;

           对于上面两个SQL来说,第一个可以返回所有记录,第2个SQL返回0条记录;
           原因是Oracle扫描第1条记录时,因为不满足而无法输出,因此rownum序列重新置0,然后永远因无法满足条件而不能输出,最终返回0条记录。包括rownum=2也由于此原因不能得到记录。
 
           所以当需要rownum >= n 时,需要先把rownum转化为实列,例如:

    select num from

    ( select num, rownum  rn fromt1)

    where rn >= 10 ;

 

 

    另外,rownum列不能加任何基表的前缀,例如:

    select id,t1.rownum from t1;  --ORA-01747: invalid user.table.column specification

 

 

2、对表排序,再取出第i到第j条记录:

 

    select * from

    ( select num, rownum rn from

    ( select num from t1 order by id ))

    where rn between 5 and 10 ;

 

     注意:千万不能使用以下方法

    select * from

    (select num from t1 order by id)

    where rownum <= 10

    minus

    select * from

    (select num from t1 order by id)

    where rownum <= 4 ; ----会发生错误,因为minus自动distinct

 

 

3、order  by的一些特性:

 

    (select * from t1);

    select * from t1 order by id;

    (select * from t1 order by id);--发生错误ORA-00907: missing right parenthesis

    (select * from t1 )order by id;

    select * from (select * from t1 order by id);

     其中除第3个外,其余均可正确执行,主要是由于Oracle的解析规则造成,修改成第4种方式即可。

 

 

4、一条关于rownum语句的问题:

 

    select * from t1 where rownum <= 10 order by id desc;

    select * from t1 where rownum <= 10 order by num desc;

     比较上面两条语句,唯一的区别是id字段上有索引,num字段没有索引

 

    乍一看这两条语句都会先进行筛选rownum <= 10 然后再排序,则得出的结果集应该是相同的10行记录

    但是实际上两条语句运行出来的结果是完全不同的

    主要的原因还是由于RBO会判断排序字段是否有索引,如果存在索引,就先排序,然后进行rownum筛选,如果字段无索引则先进行筛选再排序。

 

 

5、标准SQL函数row_number() over()的用法:

 

    select id,num,row_number() over(partition by id order by num) from t1;

    即对id分组后,再按照num的排列顺序取出一次的row_number

    在实际应用中可以取出例如:每个班的最后10名的成绩,每个月最大的20比交易等等。

 

 

6、使用rownum提取依次的序列:

 

     这是一个比较基本的应用了:

    select rownum from dual connect by rownum<=10;

           把rownum换成level的效果也是一样:

    select level from dual connect by level<=10;

 

     这个在实际的应用还是比较广泛的,例如:列出当月的所有天数

    select trunc(sysdate,'mm')+rownum-1 as everyday from dual

    connect by rownum <= to_number(to_char(last_day(sysdate),'dd'));

 

 





-The End-

posted on 2008-08-14 17:58 decode360-3 阅读(511) 评论(0)  编辑  收藏 所属分类: SQL Dev

只有注册用户登录后才能发表评论。


网站导航: