本文參考連接:http://blog.sina.com.cn/s/blog_8604ca230100vro9.htmlhtml
探索查詢語句:mysql
--分頁參數:size = 20 page = 2 --沒有order by的查詢 -- 嵌套子查詢,兩次篩選(推薦使用) --SELECT * -- FROM (SELECT ROWNUM AS rowno, t.* -- FROM DONORINFO t -- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') -- AND TO_DATE ('20060731', 'yyyymmdd') -- AND ROWNUM <= 20*2) table_alias -- WHERE table_alias.rowno > 20*(2-1); --耗時0.05s -- 一次篩選(數據量大的時候,第一次查詢的數據量過大,明顯比上面慢,不推薦) --select * from( --SELECT ROWNUM AS rowno, t.* --FROM DONORINFO t --WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') --) r --where r.rowno BETWEEN 20*(2-1)+1 and 20*2; --耗時0.46s --有order by的查詢 --嵌套子查詢,兩次篩選(推薦使用) --SELECT * --FROM (SELECT ROWNUM AS rowno,r.* -- FROM( -- SELECT * FROM DONORINFO t -- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') -- AND TO_DATE ('20060731', 'yyyymmdd') -- ORDER BY t.BIRTHDAY desc -- ) r -- where ROWNUM <= 20*2 -- ) table_alias -- WHERE table_alias.rowno > 20*(2-1); --耗時0.744s -- 一次篩選(數據量大的時候,第一次查詢的數據量過大,明顯比上面慢,不推薦) --select * from ( --SELECT ROWNUM AS rowno,r.* --FROM( --SELECT * FROM DONORINFO t --WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') --AND TO_DATE ('20060731', 'yyyymmdd') --ORDER BY t.BIRTHDAY desc --) r ----where ROWNUM <= 20; --這裏用>查不到數據 =也查不到數據 <= 或者 < 能夠查到數據 ----where ROWNUM BETWEEN 20*(2-1)+1 AND 20*2; --查不到數據 ----where ROWNUM <=20*2 and ROWNUM > 20*(2-1); --查不到數據 ----這是由於查詢時,第一條生成的rownum爲1,1>20不成立,1=20也不成立,因此這條數據就做廢了,依次類推,這樣就查不到任何一條數據 --) t --where t.rowno <=20*2 and t.rowno > 20*(2-1); --能夠查到數據耗時:3.924s ---- where t.rowno BETWEEN 20*(2-1)+1 AND 20*2; --能夠查到數據耗時:3.919s --採用row_number() over 分頁函數 --select * --from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber -- from DONORINFO d -- WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') -- AND TO_DATE ('20060731', 'yyyymmdd') -- ) p --where p.rownumber BETWEEN 20*(2-1)+1 AND 20*2; --耗時0.812s select * from ( select * from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber from DONORINFO d WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') ) p where p.rownumber <20*2 ) where rownumber > 20*(2-1); -- 耗時0.813s
從以上探索比較,咱們得知:sql
一、ROWNUM數據庫
rownum老是從1開始的,第一條不知足去掉的話,第二條的rownum 又成了1。依此類推,因此永遠沒有不知足條件的記錄。函數
能夠這樣理解:rownum是一個序列,是Oracle數據庫從數據文件或緩衝區中讀取數據的順序。spa
它取得第一條記錄則rownum值爲1,第二條爲2。依次類推。.net
當使用「>、>=、=、between...and」這些條件時,從緩衝區或數據文件中獲得的第一條記錄的rownum爲1,不符合sql語句的條件,會被刪除,接着取下條。code
下條的rownum還會是1,又被刪除,依次類推,便沒有了數據。htm
因此上限條件必須放在子查詢,而下限條件必須放在外層查詢。blog
二、between and 和 >= and <=
這二者查詢效率上來講沒有區別,between and 最終也是轉爲>= and <=
因此select * from (select * from a where a.time >= to_date('19920324','yyyymmdd')) b where b.time <= to_date('20170324','yyyymmdd')
這樣的嵌套是沒有必要的,能夠直接用between and。
三、Oracle通用分頁格式
對於沒有order by語句的分頁:
SELECT *
FROM (SELECT ROWNUM AS rowno, t.*
FROM DONORINFO t
WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') AND ROWNUM <= page*size) table_alias WHERE table_alias.rowno > (page-1)*size;
有order by語句的分頁
SELECT *
FROM (SELECT ROWNUM AS rowno,r.*
FROM(SELECT * FROM DONORINFO t
WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') ORDER BY t.BIRTHDAY desc ) r where ROWNUM <= page*size ) table_alias WHERE table_alias.rowno > (page-1)*size;
另外咱們也可使用row_number() over函數:
select * from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber from DONORINFO d WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') ) p where p.rownumber BETWEEN size*(page-1)+1 AND page*size;
可是相比前面的並無什麼優點。