2016-12-27 38 views
1

我對所有的常見問題及的HOWTOs建議Oracle數據庫的規範前N個查詢:rownum的訂單 - 它是否正確?

select ... from (
    select ... from ... order by ... 
) where ronwum <= N 

它完美對甲骨文11,即它在內部選擇指定的順序返回前N個記錄。

然而,它在Oracle 12上打破了。它仍然返回相同的top-N記錄,但它們可能會被混洗。這些記錄的最終順序是非確定性的。

我使用Google搜索,但沒有找到任何相關的討論。看起來其他人總是從這樣的選擇中獲得正確的記錄順序。

雖然有一個發現很有趣。我看到一些人使用(不解釋,可惜)外的額外order by rownum條款選擇:

select ... from (
    select ... from ... order by ... 
) where ronwum <= N 
order by rownum 

(包括ROWNUM在這裏是對Oracle虛列引用,它是由內選擇返回的東西)

它似乎工作。但是使用Oracle優化器,您永遠無法確定它是否只是運氣或者真正正確的解決方案。

問題是:order by rownum在這種情況下是否保證正確的排序順序,爲什麼?我和我的同事們無法就此達成一致。

P.S.我知道其他的方式來選擇前N個記錄,例如使用row_number解析函數和Oracle 12中引入的fetch first子句。我也知道,我可以在外層select上重複相同的order by ...。問題僅在於order by rownum - 是否正確。

+3

我認爲你需要重命名'rownum'的東西在內部不同select,否則外部引用引用rownum作爲外部查詢,而不引用內部查詢。 –

+1

執行此操作的正確方法是按外部查詢中的相同表達式進行排序,就像您在子查詢中所做的那樣。即使在Oracle 11和之前的版本中,從內部查詢到外部查詢的順序被保留的事實也是一個實現意外事件 - 它不能保證SQL標準。 – mathguy

回答

-1

內部查詢和外部查詢可能會或可能不會給出不同的順序,因此rownum的順序也不同。由於rownum已經訂購了,如果你想獲得最好的N條記錄,那麼最好的辦法是在內部查詢中創建rownum的別名,並在外部查詢中使用它。

選擇...從( 選擇ROWNUM RN從〜 ),其中RN < = N 爲了RN上

+1

這是行不通的,因爲rownum是在訂購之前分配的。這個查詢會給出N個完全隨機的行。 重寫查詢不是問題的關鍵。 – Alexey