Oracle SELEZIONE TOP 10 record
Domanda
Ho un grosso problema con un'istruzione SQL in Oracle. Voglio selezionare i 10 record in ordine di STORAGE_DB che non sono in un elenco da un'altra dichiarazione prescelta.
Questo funziona bene per tutti i record:
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')
Ma quando sto aggiungendo
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Sono ottenere un certo genere di "casuali" Records. Credo perché il limite avviene in vigore prima della fine.
Se qualcuno ha una buona soluzione? L'altro problema: Questa query è davvero lento (10k + record)
Soluzione
Avrete bisogno di mettere la vostra query corrente in subquery come di seguito:
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 per il risultato dopo che è stato restituito.
è necessario filtrare il risultato dopo che è stato restituito, quindi è necessario un subquery. È inoltre possibile utilizzare RANK () funzione per ottenere Top-N risultati.
Per prestazioni provare a utilizzare NOT EXISTS
al posto di NOT IN
. Vedere questo per ulteriori informazioni.
Altri suggerimenti
Se si utilizza Oracle 12c, utilizzare:
FETCH AVANTI N solo le righe
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
Più informazioni: http://docs.oracle.com/javadb /10.5.3.0/ref/rrefsqljoffsetfetch.html
Per quanto riguarda lo scarso rendimento ci sono un certo numero di cose che potrebbe essere, e dovrebbe davvero essere una questione a sé stante. Tuttavia, c'è una cosa ovvia che potrebbe essere un problema:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Se HISTORY_DATE è davvero una colonna di data e se ha un indice quindi questa riscrittura avrà un rendimento migliore:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
Questo perché una conversione tipo di dati disabilita l'utilizzo di un indice B-Tree.
try
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Si ottiene un insieme apparentemente casuale perché ROWNUM viene applicato prima ORDER BY. Quindi la query prende le prime dieci righe e tipi them.0 Per selezionare i primi dieci stipendi si dovrebbe usare una funzione analitica in una sottoquery, poi filtrare che:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10