rownum是结果集伪列,结果集第一行就是1,第二行就是2

    如果ORDER BY与ROWNUM出现在同一个查询语句中的时候,已经排好的ROWNUM可能会被打乱(因为最后执行的ORDER BY)。

    CSDN有博客讲,如果ORDER BY的字段是PK的话,会先ORDER BY然后再对查询到的结果集排ROWNUM,如果不是PK或唯一KEY的话,会先排ROWNUM再ORDER BY,但在ORACLE 12.2中实测并不是这样的,例如下面的例子(ID主键):

    1. SELECT ROWNUM,A.* FROM WLPLAT.EMPLOYEE A WHERE ROWNUM < 11 ORDER BY ID;
    2. SELECT ROWNUM,A.* FROM WLPLAT.EMPLOYEE A WHERE ROWNUM < 11 ORDER BY NAME;

    其结果分别是:

    ROWNUM ID NAME
    5 1 NAME1
    1 2 NAME2
    6 3 NAME3
    10 4 NAME4
    2 8 NAME8
    3 10 NAME10
    …. …. ….
    ROWNUM ID NAME
    5 1 NAME1
    3 10 NAME10
    4 11 NAME11
    9 13 NAME13
    1 2 NAME2
    4 3 NAME3
    …. …. ….

    可以看到ORDER BY总是最后执行的,查看EXPLAIN PLAN也是如此:
    image.png

    那到底PAGING、ROWNUM、ORDER BY怎么结合使用呢?
    1:在9(是几忘了)之后版本可以使用ROW_NUMBER函数

    1. SELECT A.*
    2. FROM (
    3. SELECT A.*, ROW_NUMBER() over (ORDER BY REC_ID) RW FROM WLPLAT.T_MM_STORAGE_DETAIL A) A
    4. WHERE RW BETWEEN 200 AND 299;

    ROW_NUMBER需要整表排序,所以消耗也大,耗时也略长

    12c中非常方便高效的取TOP N ROW的方法

    1. SELECT A.*
    2. FROM WLPLAT.T_MM_STORAGE_DETAIL A
    3. ORDER BY REC_ID
    4. FETCH FIRST 100 ROW ONLY;

    2:还是使用ROWNUM(三层查询)

    1. SELECT *
    2. FROM (
    3. SELECT A.*, ROWNUM RW
    4. FROM (
    5. SELECT A.*
    6. FROM WLPLAT.T_MM_STORAGE_DETAIL A
    7. ORDER BY REC_ID) A WHERE ROWNUM <= 299) A
    8. WHERE A.RW > 199;

    很明显多加一层避免ORDER BY 影响了 ROWNUM

    参考文档:https://docs.oracle.com/cd/E11882_01/server.112/e41084/pseudocolumns009.htm#SQLRF00255