zoukankan      html  css  js  c++  java
  • [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

  • 相关阅读:
    Java面试题—初级(4)
    Java面试题—初级(3)
    Java面试题—初级(2)
    Java面试题—初级(1)
    在ESXi使用esxcli命令強制关闭VM
    重置mysql的root密码
    通过RHN网站给RHEL打补丁
    Linux命令之rhn_check
    一键GHOST
    Http错误大全
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10504659.html
Copyright © 2011-2022 走看看