衆所周知,rownum、rowid是oracle的一個僞列,但是rownum和rowid的不同是:rowid是唯一的標識了列的存儲位置,rownum是按照用戶的插入語句順序,給一個序列號,rownum永遠是從1開始,因此,絕對不能用“rownum等於”、“rownum大於”等的條件,否則返回無結果。(因爲當前麪條件不滿足時,rownum總是從1開始。)
下面總結下rownum和order by的關係,因爲我一直會迷糊,以前還一度認爲order by排序後,rownum就會按照我們需要的順序保存,但是往往不是這樣的。
萌發這個想法也感謝以下這個帖子的五樓作者:http://www.itpub.net/thread-1352089-1-1.html
看看下面的測試:
create table test
(id number,
name varchar2(128)
);
--請注意以下的插入順序
insert into test values(3,'dfhg');
insert into test values(1,'sag');
insert into test values(4,'ashtrhf');
insert into test values(2,'lllads');
insert into test values(5,'ahd');
insert into test values(6,'dfbhfsn');
commit;
--查詢結果
select id,name,rownum
from test
order by id;
ID NAME ROWNUM
---------- ------------------------------ ----------
1 sag 2
2 lllads 4
3 dfhg 1
4 ashtrhf 3
5 ahd 5
6 dfbhfsn 6
總結:發現其實rownum並沒有按照我們要的序列產生。
爲什麼呢? 繼續看下面的語句
select id,name,rownum
from (
select id,name
from test
order by id
);
ID NAME ROWNUM
---------- ------------------------------ ----------
1 sag 1
2 lllads 2
3 dfhg 3
4 ashtrhf 4
5 ahd 5
6 dfbhfsn 6
總結:這時候按照我們要的順序了,原因:rownum是作用在一個結果集上的。
(因此,想要取前幾個序列號時,可以利用子查詢,在外層限制rownum的取值。當然也可以直接使用row_number分析函數)
繼續看下面的查詢。
我想要得到按一定順序排序的前三名。
SQL如下:
select id,name from test where rownum<4 order by id;
ID NAME
---------- ------------------------------
1 sag
3 dfhg
4 ashtrhf
說明:此時oracle先選擇,後進行了排序,(很明顯,不是我們要的結果)
繼續
select id,name
from (
select id,name
from test
order by id
)
where rownum<4;
ID NAME
---------- ------------------------------
1 sag
2 lllads
3 dfhg
總結:利用子查詢,在外層限制rownum的取值既可以實現需求。
說明:但是這種方法假設test表很大,會全表先掃描,排好序,再篩選,效率較低。在網上搜了下,但到有人這樣說:
“只需在order by字段加上索引或者主鍵約束,即可讓oracle先按照該字段排序,然後再rownum”,我試驗了下,好像不行。
連接如下:http://www.360doc.com/content/09/0218/13/6785_2578842.shtml
試驗過程如下:
1. 加入唯一索引
create unique index ind_id on test(id);
2. SQL還是原來的SQL。(結果一樣,並不是我們想要的,因此懷疑以上那句話的真實性???)
select id,name from test where rownum<4 order by id;
ID NAME
---------- ------------------------------
1 sag
3 dfhg
4 ashtrhf
說明:標紅的字體有待考證!!!