Oracle
是否可以在沒有全掃描的情況下執行跳過 N 行並獲取 M 行
假設我有這個查詢:
SELECT EMP_ID,LAST_NAME FROM EMPLOYEES WHERE POSITIONID IN (1,3) ORDER BY POSITIONID,LAST_NAME;
現在,如果我只想顯示 50 到 60 之間的前十行,我能想到的唯一方法是首先使用 ROWNUM 偽列執行上述查詢,然後從該查詢的結果中進行選擇。像這樣的東西:
SELECT EMP_ID,LAST_NAME FROM (SELECT ROWNUM RNUM,EMP_ID,LAST_NAME FROM (SELECT EMP_ID,LAST_NAME FROM EMPLOYEES WHERE POSITIONID IN (1,3) ORDER BY POSITIONID,LAST_NAME)) WHERE RNUM BETWEEN 50 AND 60;
但這樣一來,我最終會首先獲取職位為 1 或 3 的所有員工,然後提取其中的 10 行。我覺得這有點低效。有沒有辦法在不先進行全掃描的情況下實現這一目標?
獲取行 N 到 M的標準方法是執行類似的操作
SELECT * FROM (SELECT a.*, rownum rnum FROM (SELECT emp_id, last_name FROM employees WHERE positionID in (1,3) ORDER BY <<something>>) a WHERE rownum <= 60) b WHERE rnum > 50
請注意,您需要
order by
在查詢中包含 才能使其有意義。Oracle 可能會使用表掃描(取決於是否positionID
和/或其中的列order by
被索引),但會有一個停止鍵限制器,因此 Oracle 知道一旦 60 行有它就可以停止掃描表(或索引)被閱讀。在 12.1 及更高版本中,您可以稍微簡化一下
SELECT emp_id, last_nae FROM employees WHERE positionID in (1,3) ORDER BY val OFFSET 50 ROWS FETCH NEXT 10 ROWS ONLY
在 12.1中使用新行限制子句的更多範例