rownum注意問題

      衆所周知,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

 

 說明:標紅的字體有待考證!!!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章