CONAN ZONE

          你越掙扎我就越興奮

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            0 Posts :: 282 Stories :: 0 Comments :: 0 Trackbacks

          Rownum專題

           

          對于rownum來說它是oracle系統順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推,這個偽字段可以用于限制查詢返回的總行數,而且rownum不能以任何表的名稱作為前綴。
          舉例說明:
          例如表:student(學生)表,表結構為:
          ID
              char(6)           --學號
          name
            VARCHAR2(10)   --姓名

          /* Formatted on 2008/09/24 09:15 (Formatter Plus v4.8.7) */
          CREATE TABLE student (ID CHAR(6), NAME VARCHAR2(100));

          INSERT INTO student
               VALUES ('200001', '
          張一
          ');
          INSERT INTO student
               VALUES ('200002', '
          王二
          ');
          INSERT INTO student
               VALUES ('200003', '
          李三
          ');
          INSERT INTO student
               VALUES ('200004', '
          趙四
          ');
          COMMIT ;


          (1) rownum
          對于等于某值的查詢條件

          如果希望找到學生表中第一條學生的信息,可以使用rownum=1作為條件。但是想找到學生表中第二條學生的信息,使用rownum=2結果查不到數據。因為rownum都是從1開始,但是1以上的自然數在rownum做等于判斷是時認為都是false條件,所以無法查到rownum = nn>1的自然數)。
          SQL> select rownum,id,name from student where rownum=1;
          (可以用在限制返回記錄條數的地 方,保證不出錯,如:隱式游標)
          SQL> select rownum,id,name from student where rownum=1;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200001
          張一
          SQL> select rownum,id,name from student where rownum =2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------

          2rownum對于大于某值的查詢條件
            
          如果想找到從第二行記錄以后的 記錄,當使用rownum>2是查不出記錄的, 原因是由于rownum是一個總是從1開始的偽列,Oracle 認為rownum> n(n>1的自然數)這種條件依舊不成立,所以查不到記錄
          SQL> select rownum,id,name from student where rownum >2;
          ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
          那如何才能找到第二行以后的記 錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會查出記錄來,這是因為rownum不是某個表的列,如果不起別名的話,無法知道rownum是子查詢的列還是主查詢的列。
          SQL>select * from(select rownum no ,id,name from student) where no>2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003
          李三
                   4 200004
          趙四
          SQL> select * from(select rownum,id,name from student)where rownum>2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------

          3rownum對于小于某值的查詢條件
          如果想找到第三條記錄以前的記 錄,當使用rownum<3是能得到兩條記錄 的。顯然rownum對于rownum<n(n>1的自然數)的條件認為是成立的,所以可以找到記錄。
          SQL> select rownum,id,name from student where rownum <3;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                  1 200001
          張一
                  2 200002
          王二

          綜上幾種情況,可能有時候需要 查詢rownum在某區間的數據,那怎么辦呀從上可以看出rownum對小于某值的查詢條件是人為true的,rownum對于大于某值的查詢條件直接認為是false的,但是可以間接的讓它轉為認為是true的。那就必須使用子查詢。例如要查詢rownum在第二行到第三行之間的數據,包括第二行和第三行數據,那么我們只能寫以下語句,先讓它返回小于等于 三的記錄行,然后在主查詢中判斷新的rownum的別名 列大于等于二的記錄行。但是這樣的操作會在大數據集中影響速度。
          SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   2 200002
          王二
                   3 200003
          李三

          4rownum和排序
          Oracle
          中的rownum的是在取數據的時候產生的序號,所以想對指定排序的數據去指定的rowmun行數據就必須注意了。
          SQL> select rownum ,id,name from student order by name;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003
          李三
                   2 200002
          王二
                   1 200001
          張一
                   4 200004
          趙四
          可以看出,rownum并不是按照name列來生成的序號。系統是按照記錄插入時的順序給記錄排的號,rowid也是順序分配的。為了解決這個問題,必須使用子查詢
          SQL> select rownum ,id,name from (select * from student order by name);
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200003
          李三
                   2 200002
          王二
                   3 200001
          張一
                   4 200004
          趙四
          這樣就成了按name排序,并且用rownum標出正確序號(有小到大)。

          筆者在工作中有一上百萬條記錄的表,在jsp頁面中需對該表進行分頁顯示, 便考慮用rownum來作,下面是具體方法(每頁
          顯示20)
          “select * from tabname where rownum<20 order by name"
          但卻發現oracle卻不能按自己的意愿來執行,而是先隨便

          20條記錄,然后再 order by,后經咨詢oracle,rownum確實就這樣,想用的話,只能用子查詢 來實現先排序,后
          rownum
          ,方法如下:
          "select * from (select * from tabname order by name) where rownum<20",
          但這樣一來,效率會較低很多。

          后經筆者試驗,只需在order by 的字段上加主鍵或索引即可讓oracle先按 該字段排序,然后再rownum;方法不變:

             “select * from tabname where rownum<20 order by name"


          補充:我們正常分頁是如下(order by 主鍵,在最里面的那一層。非主鍵字段同樣要 加索引):
          /* Formatted on 2008/09/24 12:14 (Formatter Plus v4.8.7) */
          SELECT *
          FROM (SELECT tmp.*, ROWNUM rn
                    FROM (SELECT   *
                              FROM student
                             WHERE 1 = 1
                          ORDER BY NAME DESC) tmp
                   WHERE 1 = 1 AND ROWNUM <= 3)
          WHERE 1 = 1 AND rn >= 2



          (5)
          取得某列中第N大的行

          select column_name from
          (select table_name.*,dense_rank() over (order by column desc) rank from table_name)
          where rank = &N


          /* Formatted on 2008/09/24 12:30 (Formatter Plus v4.8.7) */
          SELECT *
          FROM (SELECT student.*, DENSE_RANK () OVER (ORDER BY ID DESC) RANK
                    FROM student)
          WHERE RANK = 2


          (6)
          假如要返回前5條記錄:

          select * from tablename where rownum<6;(
          或是rownum <= 5 或是
          rownum != 6)
          假如要返回第5-9條記錄:

          /* Formatted on 2008/09/24 12:34 (Formatter Plus v4.8.7) */
          SELECT   *
              FROM student
             WHERE ROWNUM < 4
          MINUS
          SELECT   *
              FROM student
             WHERE ROWNUM < 2


          order by name
          選出結果后用name排序顯示結果。(先選再排序)

          注意:只能用以上符號(<<=!=)


          (7)select * from tablename where rownum != 10;
          返回的是前9條記錄。

          不能用:>,>=,=,Between...and。由于rownum是一個總是從1開始的偽列,Oracle 認為這種條件 不成立,查不到記錄
          .

          另 外,這個方法更快:


          select * from (
          select rownum r,a from yourtable
          where rownum <= 20
          order by name )
          where r > 10
          這樣取出第11-20條記錄!(先選再排序再選
          )

          要先排序再選則須用select嵌套:內層排序外層選。

          rownum
          是隨著結果集生成的,一旦生成,就不會變化了;同時,生成的結果 是依次遞加的,沒有1就永遠不會有2!

          rownum
          是在 查詢集合產生的過程中產生的偽列,并且如果where條件中存在 rownum 條件的話,則:

          1
          假如 判定條件是常量,則:

          只能 rownum = 1, <= 大于1 的自然數, = 大于1 的數是沒有結果的, 大于一個數也是沒有結果的

          當出現一個 rownum 不滿足條件的時候則 查詢結束   
          this is stop key!

          2:
          當判 定值不是常量的時候

          若條件是 = var , 則只有當 var 1 的時候才滿足條件,這個時候不存在 stop key ,必須進行 full scan ,對每個滿足其他where條件的數據進行判定

          選出一行后才能去選rownum=2的行……

          posted on 2010-05-03 19:46 CONAN 閱讀(451) 評論(0)  編輯  收藏 所屬分類: SQLOracle
          主站蜘蛛池模板: 广德县| 清苑县| 安仁县| 平凉市| 溆浦县| 灯塔市| 阳朔县| 罗江县| 怀仁县| 肇东市| 连江县| 万载县| 鹤壁市| 慈利县| 绿春县| 湟源县| 加查县| 德令哈市| 鄯善县| 三原县| 东安县| 绥中县| 连南| 波密县| 颍上县| 固阳县| 扎囊县| 嵊州市| 宜兰市| 成武县| 凤山市| 汤阴县| 武威市| 象山县| 洱源县| 肃北| 孟村| 石河子市| 安平县| 桓台县| 马鞍山市|