Mam duży problem z instrukcją SQL w Oracle. Chcę wybrać TOP 10 rekordów uporządkowanych przez STORAGE_DB, których nie ma na liście z innej instrukcji Select.
Ten działa dobrze dla wszystkich rekordów:
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')
Ale kiedy dodam
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Dostaję jakieś „przypadkowe” nagrania. Myślę, że ponieważ limit ma miejsce przed zamówieniem.
Czy ktoś ma dobre rozwiązanie? Inny problem: to zapytanie jest naprawdę powolne (ponad 10 000 rekordów)
Odpowiedzi:
Musisz umieścić swoje aktualne zapytanie w podzapytaniu, jak poniżej:
Oracle stosuje rownum do wyniku po jego zwróceniu.
Musisz przefiltrować wynik po jego zwróceniu, więc wymagane jest podzapytanie. Możesz również użyć funkcji RANK (), aby uzyskać najlepsze wyniki.
Aby uzyskać wydajność, spróbuj użyć
NOT EXISTS
zamiastNOT IN
. Zobacz to po więcej.źródło
FETCH NEXT N ROWS ONLY
odpowiedź poniżej.Jeśli używasz Oracle 12c, użyj:
Więcej informacji: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html
źródło
Jeśli chodzi o słabą wydajność, może to być wiele rzeczy i to naprawdę powinno być osobną kwestią. Jest jednak jedna oczywista rzecz, która może stanowić problem:
Jeśli HISTORY_DATE naprawdę jest kolumną daty i jeśli ma indeks, to przepisanie będzie działać lepiej:
Dzieje się tak, ponieważ konwersja typu danych wyłącza użycie indeksu B-Tree.
źródło
próbować
źródło
Otrzymujesz pozornie losowy zestaw, ponieważ ROWNUM jest stosowane przed ORDER BY. Więc twoje zapytanie bierze pierwsze dziesięć wierszy i sortuje je.0 Aby wybrać dziesięć najwyższych pensji, powinieneś użyć funkcji analitycznej w podzapytaniu, a następnie odfiltrować to:
źródło