Ik heb een groot probleem met een SQL verklaring in Oracle. Ik wil de TOP 10 Records selecteren gerangschikt op STORAGE_DB die'niet in een lijst staan van een andere select statement.
Deze werkt prima voor alle records:
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')
Maar wanneer ik
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
krijg ik een soort van "random" Records. Ik denk omdat de limiet op zijn plaats gaat voor de order.
Heeft iemand een goede oplossing? Het andere probleem: Deze query is echt traag (10k+ records)
U'll moet uw huidige query in subquery zetten zoals hieronder :
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
Oracle past rownum toe op het resultaat nadat het is geretourneerd.
Je moet het resultaat filteren nadat het is geretourneerd, dus een subquery is vereist. Je kunt ook de RANK() functie gebruiken om Top-N resultaten te krijgen.
Probeer voor de performance NOT EXISTS
te gebruiken in plaats van NOT IN
. Zie this voor meer.
Wat de slechte prestaties betreft, zijn er een aantal dingen die het zouden kunnen zijn, en dat zou eigenlijk een afzonderlijke vraag moeten zijn. Er is echter één voor de hand liggend ding dat een probleem zou kunnen zijn:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Als HISTORY_DATE echt een datumkolom is en als die een index heeft, dan zal deze herschrijving beter presteren:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
Dit komt omdat een datatype conversie het gebruik van een B-Tree index uitschakelt.
Je krijgt een schijnbaar willekeurige set omdat ROWNUM wordt toegepast vóór de ORDER BY. Dus je query neemt de eerste tien rijen en sorteert ze.0 Om de top tien salarissen te selecteren moet je een analytische functie in een subquery gebruiken, en die vervolgens filteren:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10