oracle中無limit占贫,實現(xiàn)此功能需要使用rownum型奥,如limit10:
select * from tableName where rownum <= 10;
返回11到20行:
select * from (select rownum rn,t.* from tableName t) where rn<=20 and rn >=11;
1.無ORDER BY排序的寫法厢汹。(效率最高)
(經(jīng)過測試烫葬,此方法成本最低,只嵌套一層,速度最快!即使查詢的數(shù)據(jù)量再大月匣,也幾乎不受影響锄开。)
SELECT *
FROM (SELECT ROWNUM AS rowno, t.*
FROM emp t
WHERE hire_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060731', 'yyyymmdd')
AND ROWNUM <= 20) table_alias
WHERE table_alias.rowno >= 10;
2.有ORDER BY排序的寫法。(效率較高)
(經(jīng)過測試称诗,此方法隨著查詢范圍的擴大萍悴,速度也會越來越慢!)
SELECT *
FROM (SELECT tt.*, ROWNUM AS rowno
FROM ( SELECT t.*
FROM emp t
WHERE hire_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060731', 'yyyymmdd')
ORDER BY create_time DESC, emp_no) tt
WHERE ROWNUM <= 20) table_alias
WHERE table_alias.rowno >= 10;
3.無ORDER BY排序的寫法寓免。(建議使用方法1代替)
(此方法隨著查詢數(shù)據(jù)量的擴張癣诱,速度會越來越慢!)
SELECT *
FROM (SELECT ROWNUM AS rowno, t.*
FROM k_task t
WHERE flight_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060731', 'yyyymmdd')) table_alias
WHERE table_alias.rowno <= 20 AND table_alias.rowno >= 10;
--TABLE_ALIAS.ROWNO between 10 and 100;
4.有ORDER BY排序的寫法.(建議使用方法2代替)
(此方法隨著查詢范圍的擴大袜香,速度會越來越慢撕予!)
SELECT *
FROM (SELECT tt.*, ROWNUM AS rowno
FROM ( SELECT *
FROM k_task t
WHERE flight_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060531', 'yyyymmdd')
ORDER BY fact_up_time, flight_no) tt) table_alias
WHERE table_alias.rowno BETWEEN 10 AND 20;
5.另類語法。(有ORDER BY寫法)
(語法風格與傳統(tǒng)的SQL語法不同蜈首,不方便閱讀與理解实抡,為規(guī)范與統(tǒng)一標準欠母,不推薦使用。)
WITH partdata AS
(
SELECT ROWNUM AS rowno, tt.*
FROM ( SELECT *
FROM k_task t
WHERE flight_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060531', 'yyyymmdd')
ORDER BY fact_up_time, flight_no) tt
WHERE ROWNUM <= 20)
SELECT *
FROM partdata
WHERE rowno >= 10;
6另類語法 吆寨。(無ORDER BY寫法)
WITH partdata AS
(
SELECT ROWNUM AS rowno, t.*
FROM k_task t
WHERE flight_date BETWEEN TO_DATE ('20060501', 'yyyymmdd')
AND TO_DATE ('20060531', 'yyyymmdd')
AND ROWNUM <= 20)
SELECT *
FROM partdata
WHERE rowno >= 10;
分析
Oracle的分頁查詢語句基本上可以按照本文給出的格式來進行套用赏淌。
分頁查詢格式:
SELECT *
FROM (SELECT a.*, ROWNUM rn
FROM (SELECT *
FROM table_name) a
WHERE ROWNUM <= 40)
WHERE rn >= 21
其中最內(nèi)層的查詢SELECT * FROM TABLE_NAME表示不進行翻頁的原始查詢語句。ROWNUM <= 40和RN >= 21控制分頁查詢的每頁的范圍啄清。
上面給出的這個分頁查詢語句六水,在大多數(shù)情況擁有較高的效率。分頁的目的就是控制輸出結(jié)果集大小辣卒,將結(jié)果盡快的返回掷贾。在上面的分頁查詢語句中,這種考慮主要體現(xiàn)在WHERE ROWNUM <= 40這句上荣茫。
選擇第21到40條記錄存在兩種方法胯盯,一種是上面例子中展示的在查詢的第二層通過ROWNUM <= 40來控制最大值,在查詢的最外層控制最小值计露。而另一種方式是去掉查詢第二層的WHERE ROWNUM <= 40語句,在查詢的最外層控制分頁的最小值和最大值憎乙。這是票罐,查詢語句如下:
SELECT *
FROM (SELECT a.*, ROWNUM rn
FROM (SELECT *
FROM table_name) a)
WHERE rn BETWEEN 21 AND 40
對比這兩種寫法,絕大多數(shù)的情況下泞边,第一個查詢的效率比第二個高得多该押。
這是由于CBO優(yōu)化模式下,Oracle可以將外層的查詢條件推到內(nèi)層查詢中阵谚,以提高內(nèi)層查詢的執(zhí)行效率蚕礼。對于第一個查詢語句,第二層的查詢條件WHERE ROWNUM <= 40就可以被Oracle推入到內(nèi)層查詢中梢什,這樣Oracle查詢的結(jié)果一旦超過了ROWNUM限制條件奠蹬,就終止查詢將結(jié)果返回了。
而第二個查詢語句嗡午,由于查詢條件BETWEEN 21 AND 40是存在于查詢的第三層囤躁,而Oracle無法將第三層的查詢條件推到最內(nèi)層(即使推到最內(nèi)層也沒有意義,因為最內(nèi)層查詢不知道RN代表什么)荔睹。因此狸演,對于第二個查詢語句,Oracle最內(nèi)層返回給中間層的是所有滿足條件的數(shù)據(jù)僻他,而中間層返回給最外層的也是所有數(shù)據(jù)宵距。數(shù)據(jù)的過濾在最外層完成,顯然這個效率要比第一個查詢低得多吨拗。
上面分析的查詢不僅僅是針對單表的簡單查詢满哪,對于最內(nèi)層查詢是復雜的多表聯(lián)合查詢或最內(nèi)層查詢包含排序的情況一樣有效婿斥。
這里就不對包含排序的查詢進行說明了,下一篇文章會通過例子來詳細說明翩瓜。
下面簡單討論一下多表聯(lián)合的情況受扳。
對于最常見的等值表連接查詢,CBO一般可能會采用兩種連接方式NESTED LOOP和HASH JOIN(MERGE JOIN效率比HASH JOIN效率低兔跌,一般CBO不會考慮)勘高。在這里,由于使用了分頁坟桅,因此指定了一個返回的最大記錄數(shù)华望,NESTED LOOP在返回記錄數(shù)超過最大值時可以馬上停止并將結(jié)果返回給中間層,而HASH JOIN必須處理完所有結(jié)果集(MERGE JOIN也是)仅乓。那么在大部分的情況下赖舟,對于分頁查詢選擇NESTED LOOP作為查詢的連接方法具有較高的效率(分頁查詢的時候絕大部分的情況是查詢前幾頁的數(shù)據(jù),越靠后面的頁數(shù)訪問幾率越锌溟埂)宾抓。
因此,如果不介意在系統(tǒng)中使用HINT的話豫喧,可以將分頁的查詢語句改寫為:
SELECT *
FROM (SELECT a.*, ROWNUM rn
FROM (SELECT *
FROM table_name) a
WHERE ROWNUM <= 40)
WHERE rn >= 21
————————————————
版權(quán)聲明:本文為CSDN博主「huahua.Dr」的原創(chuàng)文章石洗,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明紧显。
原文鏈接:https://blog.csdn.net/use_admin/article/details/83622414