Oracle SELECT TOP 10 Datensätze
Frage
Ich habe ein großes Problem mit einer SQL-Anweisung in Oracle. Ich möchte die TOP 10 Records sortiert von STORAGE_DB auszuwählen, die von einer anderen select-Anweisung nicht in einer Liste enthalten sind.
Dies funktioniert gut für alle Datensätze:
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')
Aber wenn ich das Hinzufügen
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Ich erhalte eine Art von „random“ Aufzeichnungen. Ich denke, weil die Grenze an Ort und Stelle vor der Reihenfolge.
Hat jemand eine gute Lösung? Das andere Problem: Diese Abfrage ist wirklich langsam (10k + Datensätze)
Lösung
Sie müssen Ihre aktuelle Abfrage in Unterabfrage setzen, wie unten:
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 gilt rownum zu dem Ergebnis, nachdem er zurückgekehrt ist.
Sie müssen das Ergebnis filtern, nachdem er zurückgekehrt ist, so eine Unterabfrage benötigt wird. Sie können auch RANK () Funktion erhalten Top-N verwenden Ergebnisse.
Für Leistung versuchen NOT EXISTS
anstelle von NOT IN
verwenden. Siehe diese mehr.
Andere Tipps
Wenn Sie mit Oracle 12c, zu verwenden:
FETCH NEXT- N ROWS ONLY
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
Mehr Infos: http://docs.oracle.com/javadb /10.5.3.0/ref/rrefsqljoffsetfetch.html
Im Hinblick auf die schlechte Leistung gibt es eine beliebige Anzahl von Dingen, könnte es sein, und es soll wirklich eine andere Frage sein. Allerdings gibt es eine offensichtliche Sache, die ein Problem sein könnte:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Wenn HISTORY_DATE wirklich eine Datumsspalte und wenn es einen Index hat, dann wird dies Rewrite eine bessere Leistung:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
Das ist, weil eine Datentyp-Konvertierung die Verwendung eines Index B-Struktur deaktiviert.
Versuch
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Sie haben einen scheinbar zufälligen Satz bekommen, weil ROWNUM BY, bevor der Auftrag angewendet wird. So Ihre Abfrage die ersten zehn Zeilen und Sorten nimmt them.0 die Top Ten der Gehälter So wählen Sie eine analytische Funktion in einer Unterabfrage verwendet werden soll, dann Filter, dass:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10