设为首页 加入收藏

TOP

[Oracle]ROWNUM和分页
2015-07-24 11:29:39 来源: 作者: 【 】 浏览:3
Tags: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
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇三种启动SQLSERVER服务的方法(安.. 下一篇ORACLE函数之日期时间转换函数

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·nginx 监听一个端口 (2025-12-25 00:19:30)
·整个互联网就没有一 (2025-12-25 00:19:27)
·囧次元最新官网入口 (2025-12-25 00:19:24)
·如何利用Python做数 (2025-12-24 23:48:36)
·如何使用python进行 (2025-12-24 23:48:34)