您的位置:首页 > 数据库 > Oracle

Rownum,Rowid,row_number()及oracle分页查询

2018-02-08 22:36 573 查看
1.
rownum
rowid
都是伪列,但两者的根本是不同的,
rownum
是根据
sql
查询出来的结果给每行分配一个

逻辑编号,不同的
sql
也就会导致
rownum
不同,但是rowid是物理结构上的,在每条记录
Insert
到数据库时,

就会有一个唯一的物理记录。
rowid
可以说是屋里存在的,表示记录在表空间中的一个唯一位置
ID
,在
DB
中唯一。只要记录没被搬动过,
rowid
是不变的。
rowid
相对于表来说相当于一般列。

rownum
常用语分页查询,
rowid
则常用于去除重复记录。


2.
rownum
是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列(先有结果集)。简单的说,
rownum
对符合条件结果的序列号。总是从1开始排起,所以选出的结果中不能没有1而有其他大于1的值。

也可以理解为
rownum
oracle
数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则
rownum
为1,第2条为2。如果使用
>,>=,=,between...and
这些条件,因为从缓冲区或数据文件中得到的第一条记录的
rownum
为1,则被删除,接着取下条,可是
rownum
依旧为1,有被删除,便没有了数据。

case1:

SQL> select * from emp where rownum between 2 and 5;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------


case2:

SQL> select * from emp where rownum<>3;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH      CLERK      7902 1980/12/17     800.00               20
7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30


case3:

SQL> select * from emp where rownum>0;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH      CLERK      7902 1980/12/17     800.00               20
7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30
7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30
7566 JONES      MANAGER    7839 1981/4/2      2975.00               20
7654 MARTIN     SALESMAN   7698 1981/9/28     1250.00   1400.00     30
7698 BLAKE      MANAGER    7839 1981/5/1      2850.00               30
7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10
7788 SCOTT      ANALYST    7566 1987/4/19     3000.00               20
7839 KING       PRESIDENT       1981/11/17    5000.00               10
7844 TURNER     SALESMAN   7698 1981/9/8      1500.00      0.00     30
7876 ADAMS      CLERK      7788 1987/5/23     1100.00               20
7900 JAMES      CLERK      7698 1981/12/3      950.00               30
7902 FORD       ANALYST    7566 1981/12/3     3000.00               20
7934 MILLER     CLERK      7782 1982/1/23     1300.00               10
14 rows selected


case4:

SQL> select * from emp where rownum between 1 and 3;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH      CLERK      7902 1980/12/17     800.00               20
7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30
7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30


3.
rownum
row_numbe() over
:

使用
rownum
进行排序的时候是先对结果集加入伪列
rownum
然后再进行排序,而
row_number()
在包含

排序从句后是先排序再计算行号码

case:

order by:

SQL> select a.*,rownum from emp a order by a.ename;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO     ROWNUM
----- ---------- --------- ----- ----------- --------- --------- ------ ----------
7876 ADAMS      CLERK      7788 1987/5/23     1100.00               20         11
7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30          2
7698 BLAKE      MANAGER    7839 1981/5/1      2850.00               30          6
7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10          7
7902 FORD       ANALYST    7566 1981/12/3     3000.00               20         13
7900 JAMES      CLERK      7698 1981/12/3      950.00               30         12
7566 JONES      MANAGER    7839 1981/4/2      2975.00               20          4
7839 KING       PRESIDENT       1981/11/17    5000.00               10          9
7654 MARTIN     SALESMAN   7698 1981/9/28     1250.00   1400.00     30          5
7934 MILLER     CLERK      7782 1982/1/23     1300.00               10         14
7788 SCOTT      ANALYST    7566 1987/4/19     3000.00               20          8
7369 SMITH      CLERK      7902 1980/12/17     800.00               20          1
7844 TURNER     SALESMAN   7698 1981/9/8      1500.00      0.00     30         10
7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30          3
14 rows selected


row_number() over(order by )

SQL> select a.*,row_number() over(order by a.ename) from emp a;
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO ROW_NUMBER()OVER(ORDERBYA.ENAM
----- ---------- --------- ----- ----------- --------- --------- ------ ------------------------------
7876 ADAMS      CLERK      7788 1987/5/23     1100.00               20                              1
7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30                              2
7698 BLAKE      MANAGER    7839 1981/5/1      2850.00               30                              3
7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10                              4
7902 FORD       ANALYST    7566 1981/12/3     3000.00               20                              5
7900 JAMES      CLERK      7698 1981/12/3      950.00               30                              6
7566 JONES      MANAGER    7839 1981/4/2      2975.00               20                              7
7839 KING       PRESIDENT       1981/11/17    5000.00               10                              8
7654 MARTIN     SALESMAN   7698 1981/9/28     1250.00   1400.00     30                              9
7934 MILLER     CLERK      7782 1982/1/23     1300.00               10                             10
7788 SCOTT      ANALYST    7566 1987/4/19     3000.00               20                             11
7369 SMITH      CLERK      7902 1980/12/17     800.00               20                             12
7844 TURNER     SALESMAN   7698 1981/9/8      1500.00      0.00     30                             13
7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30                             14
14 rows selected


4.

case1:在最外层控制分页的最小值和最大值

SELECT *
FROM (SELECT A.*, ROWNUM RN
FROM GAS_CA.A_CARD_METER_PAY A
WHERE A.PURCH_GAS_TIME BETWEEN TO_DATE('2015/1/1', 'YYYY/MM/DD') AND
TO_DATE('2016/1/1', 'YYYY/MM/DD')
AND A.ORG_NO LIKE '1009%')
WHERE RN BETWEEN 10 AND 20;


case2:

SELECT *
FROM (SELECT ROWNUM RN, A.*
FROM GAS_CA.A_CARD_METER_PAY A
WHERE A.PURCH_GAS_TIME BETWEEN TO_DATE('2015/1/1', 'YYYY/MM/DD') AND
TO_DATE('2016/1/1', 'YYYY/MM/DD')
AND A.ORG_NO LIKE '1009%'
AND ROWNUM <= 20)
WHERE RN >= 10;


对于
case1
case2
,绝大多数情况下,
case2
要比第一个查询效率高得多。

因为在
CBO
优化模式下,
oracle
可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第二份语句,

第二层的查询条件
where rownum<=40
就可以被
oracle
推入到内层查询中,这样
oracle
查询的结果一旦查过
rownum
限制的条件,

就终止查询将结果返回。而第一个语句,
oracle
无法将第三层的条件推到最内层(即使推到最内层也没有意义,因为不知道RN代表什么)。

case3:有
order by
的写法(较高效率)

SELECT T1.*, RN
FROM (SELECT ROWNUM RN, T.*
FROM (SELECT *
FROM GAS_CA.A_CARD_METER_PAY A
WHERE A.PURCH_GAS_TIME BETWEEN
TO_DATE('2015/1/1', 'YYYY/MM/DD') AND
TO_DATE('2016/1/1', 'YYYY/MM/DD')
AND A.ORG_NO LIKE '1009%'
ORDER BY A.PURCH_GAS_TIME) T
WHERE ROWNUM <= 20) T1
WHERE RN >= 10;


case4:将查询条件放置最外层

SELECT *
FROM (SELECT T.*, ROWNUM RN
FROM (SELECT *
FROM GAS_CA.A_CARD_METER_PAY A
WHERE A.PURCH_GAS_TIME BETWEEN
TO_DATE('2015/1/1', 'YYYY/MM/DD') AND
TO_DATE('2016/1/1', 'YYYY/MM/DD')
AND A.ORG_NO LIKE '1009%'
ORDER BY A.PURCH_GAS_TIME) T) T1
WHERE T1.RN BETWEEN 10 AND 20;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: