rownum详解

发表于: mysql/oracle/postgresql | 作者: darkmi | 日期: 2009/08/29 08:00
标签: rownum
字号:

含义解释:
1、rownum是oracle系统为从查询返回的行顺序分配的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数。
2、rownum不能以任何基表的名称作为前缀。

使用方法:
现有一个商品销售表sale,表结构为:

month    char(6)      --月份 
sell    number(10,2)   --月销售金额 

在数据库中创建该表,并插入测试数据:

CREATE TABLE sale (month char(6), sell number); 
INSERT INTO sale values('200001',1000); 
INSERT INTO sale values('200002',1100); 
INSERT INTO sale values('200003',1200); 
INSERT INTO sale values('200004',1300); 
INSERT INTO sale values('200005',1400); 
INSERT INTO sale values('200006',1500); 
INSERT INTO sale values('200007',1600); 
INSERT INTO sale values('200101',1100); 
INSERT INTO sale values('200202',1200); 
INSERT INTO sale values('200301',1300); 
INSERT INTO sale values('200008',1000); 
commit; 

限制返回记录条数:

SQL> SELECT rownum, month, sell FROM sale WHERE rownum=1;

    ROWNUM MONTH  SELL
---------- ------ ----
         1 200001 1000

rownum使用1以上都查不到记录:

SQL> SELECT rownum, month, sell FROM sale WHERE rownum=2;

    ROWNUM MONTH  SELL
---------- ------ ----

由于rownum是一个总是从1开始的伪列,Oracle 认为以下条件不成立,查不到记录:

SQL> SELECT rownum, month, sell FROM sale WHERE rownum > 5;

    ROWNUM MONTH  SELL
---------- ------ ----

只返回前3条纪录

SQL> SELECT rownum, month, sell FROM sale WHERE rownum <4;

    ROWNUM MONTH  SELL
---------- ------ ----
         1 200001 1000
         2 200002 1100
         3 200003 1200

如何用rownum实现大于、小于逻辑?

SQL> SELECT rownum, month, sell FROM sale WHERE rownum <10 minus
  2  SELECT rownum, month, sell FROM sale WHERE rownum <5;

    ROWNUM MONTH        SELL
---------- ------ ----------
         5 200005       1400
         6 200006       1500
         7 200007       1600
         8 200101       1100
         9 200202       1200

上面的sql语句通过minus操作返回rownum在4—10之间的数据,速度会受影响。

想按日期排序,并且用rownum标出正确序号(由小到大)

SQL> SELECT rownum, month, sell FROM sale ORDER BY month;

    ROWNUM MONTH  SELL
---------- ------ ----
         1 200001 1000
         2 200002 1100
         3 200003 1200
         4 200004 1300
         5 200005 1400
         6 200006 1500
         7 200007 1600
        11 200008 1000
         8 200101 1100
         9 200202 1200
        10 200301 1300

11 rows selected

可以发现,rownum并没有实现我们的意图,系统是按照记录入库时的顺序给记录排的号,rowid也是顺序分配的。

SQL> SELECT rowid, rownum, month, sell FROM sale ORDER BY rowid;

ROWID                  ROWNUM MONTH  SELL
------------------ ---------- ------ ----
AAAEbhAAJAAACK1AAA          1 200001 1000
AAAEbhAAJAAACK1AAB          2 200002 1100
AAAEbhAAJAAACK1AAC          3 200003 1200
AAAEbhAAJAAACK1AAD          4 200004 1300
AAAEbhAAJAAACK1AAE          5 200005 1400
AAAEbhAAJAAACK1AAF          6 200006 1500
AAAEbhAAJAAACK1AAG          7 200007 1600
AAAEbhAAJAAACK1AAH          8 200101 1100
AAAEbhAAJAAACK1AAI          9 200202 1200
AAAEbhAAJAAACK1AAJ         10 200301 1300
AAAEbhAAJAAACK1AAK         11 200008 1000

11 rows selected

正确用法,使用子查询

SQL> SELECT rownum,month,sell FROM (SELECT month,sell FROM sale GROUP BY month,sell) WHERE rownum<13;

    ROWNUM MONTH  SELL
---------- ------ ----
         1 200001 1000
         2 200002 1100
         3 200003 1200
         4 200004 1300
         5 200005 1400
         6 200006 1500
         7 200007 1600
         8 200008 1000
         9 200101 1100
        10 200202 1200
        11 200301 1300

11 rows selected

按销售金额排序,并且用rownum标出正确序号(由小到大)

SQL> SELECT rownum,month,sell FROM (SELECT month,sell FROM sale GROUP BY sell,month) WHERE rownum<13;

    ROWNUM MONTH  SELL
---------- ------ ----
         1 200001 1000
         2 200008 1000
         3 200002 1100
         4 200101 1100
         5 200003 1200
         6 200202 1200
         7 200004 1300
         8 200301 1300
         9 200005 1400
        10 200006 1500
        11 200007 1600

11 rows selected

利用以上方法,如在打印报表时,想在查出的数据中自动加上行号,就可以利用rownum。

返回第5—9条纪录,按月份排序

SQL> SELECT * FROM (SELECT rownum row_id ,month,sell
  2  		       FROM (SELECT month, sell FROM sale group by month,sell))
  3  WHERE row_id BETWEEN 5 AND 9;

ROW_ID MONTH  SELL
------ ------ ----
     5 200005 1400
     6 200006 1500
     7 200007 1600
     8 200008 1000
     9 200101 1100

====================================================
下面是其他读者写的:
Oracle分页SQL
以前记在笔记上的一点东西,贴上来,省得以后丢了笔记,忘记了
Oracle 分页
select a.*, rownum r
from (select * from lg_order o order by o.order_id) a
where rownum <= 20
and rownum >= 10

select *
from (select a.*, rownum r
from (select * from lg_order o order by o.order_id) a
where rownum <= 20) b
where r >= 10

select *
from (select rid
from (select rownum rn, rid
from (select rowid rid from lg_order o order by o.order_id)
where rownum <= 20)
where rn >= 10) t1,
lg_order t2
where t2.rowid = t1.rid

第一句是错误的 由于rownum是一个总是从1开始的伪列,Oracle 认为这种条件不成立,查不到记录,执行顺序从内到外,从右到左 直接取物理地址最快

from:http://edu.codepub.com/2009/0525/4637.php

切换主题切换主题
返回顶部