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

此条目发表在DB/ES分类目录,贴了标签。将固定链接加入收藏夹。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据