[Oracle] ROWNUM和分页

rownum是oracle的一个伪劣,它的顺序根据从表中获取记录的顺序递增,这里要注意的是:由于记录在表中是无序存放的,因此你无法通过简单的rownum和order by的组合获得类似TOP N的结果。

我们的测试数据如下:

 select * from test;

        ID NAME
---------- --------------------
         1 A
         3 C
         4 C
         8 C
        10 D
         2 B
         5 C
         7 C
         6 C
         9 D

通过rownum<=5可以获得前5行数据:

select * from test where rownum<=5;

        ID NAME
---------- --------------------
         1 A
         3 C
         4 C
         8 C
        10 D

如果你想获得像top n那样的结果,必须使用子查询:

select * from (select * from test order by id) where rownum<=5;

        ID NAME
---------- --------------------
         1 A
         2 B
         3 C
         4 C
         5 C

如果你想获得第5行到第10行之间的数据,则必须再加一层子查询:

 select T.* from (select t.*,rownum rn from (select * from test order by id) t where rownum<=10) T where T.rn>5;

        ID NAME                         RN
---------- -------------------- ----------
         6 C                             6
         7 C                             7
         8 C                             8
         9 D                             9
        10 D                            10

其实上面的写法是由陷阱的,不信你把order by id换成order by name试试看:

select * from (select * from test order by name) where rownum<=5;

        ID NAME
---------- --------------------
         1 A
         2 B
         3 C
         4 C
         8 C
 select T.* from (select t.*,rownum rn from (select * from test order by name) t where rownum<=10) T where T.rn>5;

        ID NAME                         RN
---------- -------------------- ----------
         5 C                             6
         4 C                             7
         8 C                             8
        10 D                             9
         9 D                            10

你会惊奇的发现id=4这条数据出现在了两个地方,这不合逻辑!但事实就是这样的,为什么呢?因为name不唯一,两次排序取出的结果有可能会不一样,我还是举个例子吧:

 select id,name,rank() over(order by name) from test;

        ID NAME                 RANK()OVER(ORDERBYNAME)
---------- -------------------- -----------------------
         1 A                                          1
         2 B                                          2
         6 C                                          3
         3 C                                          3
         4 C                                          3
         8 C                                          3
         5 C                                          3
         7 C                                          3
         9 D                                          9
        10 D                                          9

从上面的结果我们不难发现,根据name排序,有多条数据并列排在第3位,这样,当取前5名时,到底在并列第3中取哪几位就不是确定的事,因此就出现了之前出现的诡异的问题。那么,怎样才能彻底解决这个问题呢?其实只要在order by name后面加上rowid,保证不会出现并列的情况就可以了,如下所示:

 select * from (select * from test order by name,rowid) where rownum<=5;

        ID NAME
---------- --------------------
         1 A
         2 B
         3 C
         4 C
         8 C
select T.* from (select t.*,rownum rn from (select * from test order by name,rowid) t where rownum<=10) T where T.rn>5;

        ID NAME                         RN
---------- -------------------- ----------
         5 C                             6
         7 C                             7
         6 C                             8
        10 D                             9
         9 D                            10

[Oracle] ROWNUM和分页

时间: 2024-10-20 00:04:14

[Oracle] ROWNUM和分页的相关文章

Oracle下用rownum进行分页时排序的错乱 .

今天早上用户打电话说系统的排序有问题,仔细看了一下,问题好像是出在ROWNUM这个函数上. 在Oracle下ROWNUM函数是对查询结果按照顺序分配自增行序号,所以很多人都利用这个特点进行分页操作,即rownum between 30 and 60,这种限制返回行数的小窍门在普通情况下都很正常,但如果要对返回结果在进行排序就变得乱套了. 如下查询: select page.* from( select rownum page_id,    id,    unit_code,    name,  

Oracle rownum影响执行计划

今天调优一条SQL语句,由于SQL比较复杂,用autotrace很难一眼看出哪里出了问题,直接上10046. SELECT AB.* FROM (SELECT A.*, rownum RN FROM (SELECT * from (SELECT DISTINCT (D.DEVICE_ID), F.FUNCTION_LOCATION_ID from GG_device D, GG_CLASSIFY_CARD C, GG_function_location F, GG_fl_device L, GG

Oracle数据库查询分页SQL语句

Oracle数据库查询分页数据SQL语句: select * from (select a.*,rownum row_num from (select * from mytable t order by t.id desc) a ) b where b.row_num between 1 and 10

Oracle数据库JSP分页

创建表 create table t_user( username varchar(20), password varchar(20)); insert into t_user values('aa','aa'); 导入jdbc驱动 e:\oracle\product\10.1.0\Db_3\jdbc\lib\ojdbc14.jar 创建DB类,内容如下: package util; import java.sql.Connection; import java.sql.DriverManage

Oracle的查询-分页查询

--Oracle中的分页 --rownum行号:当我们做select操作时候 --每查询出一行记录,就在该行加上一个行号 --行号从1开始,一次递增,不能跳着走 ----emp表工资倒叙排列后,每页5条记录.查询第二页 ----排序操作会影响rownum的顺序 ----如果涉及到排序,但是还要用rownum的话.使用嵌套查询 ----rownum行号不能写大于一个正数 select * from( select rownum rn, e.* from( select * from emp ord

利用oracle rownum让表排序字段值连续

利用oracle rownum让表排序字段值连续 1.需求说明 表(eval_index)中有字段如下: 表字段 描述 说明 ID 主键 GROUP_ID 分组编号 SORT_NUM 排序序号 按照分值编号并排序:1.2.- 由于删除或其他操作,导致sort_num序号不连续:需要不改变原来的排序,保持其编号连续. 2.利用rownum功能实现 update eval_index a seta.sort_num = ( select b.rn from (select rownum rn ,id

Oracle ROWNUM用法和分页查询总结

********************************************************************************************************** [转载] Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用. Oracle分页查询格式(一):http://yangtingkun.itpub.net/post/468/100278 Oracle分页查询格式(二):http://yangtingkun.itpub.ne

oracle 分页 使用rownum的分页方式

基础知识:rownum只能做<或者<=的条件查询,如果要rownum进行51到100这样的范围判断,需要先查询出每一行的rownum,再用那个序号做判断 获取51到100的数据三种分页的写法:1.使用minus,原理就是查询出前100行的数据 减去 查询出前50行的数据 select * from DATA_TABLE_SQL where rownum<=100 minus select * from DATAT_ABLE_SQL where rownum<=50 2.查询出所有数

oracle rownum 注意事项

1.使用rownum一定要包含第一条记录,如果不包含第一条记录,则不会返回结果.因为rownum是伪列,是有结果集之后再加上的列.而且是从1开始排列的. 2.在使用rownum时,只有东order by的字段是主键时,查询结果才会先排序后再计算rownum,反之,如果排序字段不是主键,则会出现先有rownum,在对结果集进行排序的情况. 3.排序分页是注意,oracle对排序结果及做了优化,如果排序字段存在多条相同记录时,可能在多页中出现相同的记录:解决方法是排序时,除了使用原本的排序字段,在加