2010-03-23 127 views
85

我在Oracle中有一個SQL語句的大問題。我想選擇STORAGE_DB訂購的不在其他選擇語句列表中的TOP 10 Records。Oracle SELECT TOP 10條記錄

這其中的所有記錄正常工作:

SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
     STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID 
         FROM HISTORY 
         WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

但是,當我加入

AND ROWNUM <= 10 
ORDER BY STORAGE_GB DESC 

我得到某種「隨機」記錄。我認爲是因爲限制在訂單之前已經到位。

有人有一個很好的解決方案嗎?另一個問題:該查詢是真的慢(10K +記錄)

+0

可能的重複:http://stackoverflow.com/questions/2306744/oracle-sql-how-to-retrieve-highest-5-values-of-a-column – APC 2010-03-23 06:48:38

回答

142

你需要把在子查詢當前的查詢如下:

SELECT * FROM (
    SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') 
    ORDER BY STORAGE_GB DESC) 
WHERE ROWNUM <= 10 

甲骨文適用rownum的結果已經返回後。
您需要在返回結果後過濾結果,因此需要子查詢。您還可以使用RANK()函數獲取Top-N結果。

對於性能嘗試使用NOT EXISTS代替NOT IN。有關更多信息,請參閱this

+0

NOT EXISTS在這種情況下不起作用(無效關係運算符)APP_ID NOT EXISTS(SELEC ...) – opHASnoNAME 2010-03-23 08:22:30

22

關於表現不佳的問題,有很多可能的事情,它應該是一個單獨的問題。但是,這可能是一個問題,一個顯而易見的事情:

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

如果HISTORY_DATE真的是一個日期列,如果它有一個索引,然後這個重寫將有更好的表現:

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY') 

這是因爲數據類型轉換禁止使用B-Tree索引。

10

由於ROWNUM應用於ORDER BY之前,因此您會得到一個明顯隨機的集合。所以你的查詢需要前10行並對它們進行排序。0,選擇排名前十的工資,你應該在子查詢中使用的解析函數,然後篩選:

select * from 
    (select empno, 
      ename, 
      sal, 
      row_number() over(order by sal desc nulls last) rnm 
    from emp) 
where rnm<=10 
11

如果您正在使用Oracle 12c中,你可以使用:

獲取下一個N行只

SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') 
    ORDER BY STORAGE_GB DESC 
FETCH NEXT 10 ROWS ONLY 

更多信息:http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

+1

簡單而重要。 FETCH NEXT 10 ROWS ONLY – 2018-02-27 12:49:58

-4

你可以只需使用TOP條款

SELECT TOP 10 * FROM TABLE;

或者

SELECT列名(多個) FROM TABLE_NAME WHERE ROWNUM < =數目;

+1

不在oracle中SQL ... – Zafi 2017-07-12 08:33:42

2

嘗試 SELECT * FROM users FETCH NEXT 10 ROWS ONLY;

+0

只適用於Oracle 12c及更高版本 – Volpato 2017-10-23 20:24:58