Oracle SELECT TOP 10 rekordów

Mam duży problem z poleceniem 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 dodaję

AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Dostaję jakieś "przypadkowe" płyty. Myślę, że ponieważ limit ma miejsce przed zamówieniem. Czy ktoś ma dobre rozwiązanie? Drugi problem: to zapytanie jest bardzo powolne (10K + rekordy)
Author: Ryan Weaver, 2010-03-23

6 answers

Musisz umieścić swoje bieżące zapytanie w subquery jak poniżej:

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 stosuje rownum do wyniku po jego zwróceniu.
musisz filtrować wynik po jego zwróceniu, więc wymagane jest zapytanie podrzędne. Możesz również użyć funkcji RANK () , aby uzyskać wyniki Top-N.

Dla wydajności spróbuj użyć NOT EXISTS zamiast NOT IN. Zobacz to Po Więcej.

 155
Author: Padmarag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-23 06:53:25

Jeśli chodzi o słabe wyniki, Jest wiele rzeczy, które mogą być, i naprawdę powinno to być osobne pytanie. Jest jednak jedna rzecz, która może być problemem:

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

Jeśli HISTORY_DATE naprawdę jest kolumną daty i jeśli ma indeks, to ta zmiana będzie działać lepiej:

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

Dzieje się tak, ponieważ konwersja typu danych wyłącza użycie indeksu drzewa B.

 22
Author: APC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-15 09:37:34

Jeśli używasz Oracle 12c, użyj:

POBIERZ NASTĘPNY N TYLKO WIERSZE

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

Więcej informacji: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

 15
Author: Volpato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 19:19:16

Otrzymujesz pozornie losowy zestaw, ponieważ ROWNUM jest stosowane przed kolejnością przez. Więc twoje zapytanie pobiera pierwsze dziesięć wierszy i sortuje je.0 aby wybrać dziesięć pierwszych pensji należy użyć funkcji analitycznej w zapytaniu podrzędnym, a następnie filtrować, że:

 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm<=10
 10
Author: vijaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 06:25:45

Try SELECT * FROM users FETCH NEXT 10 ROWS ONLY;

 4
Author: Shaaban,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 12:33:48

Możesz po prostu użyć klauzuli TOP

SELECT TOP 10 * FROM TABLE;

LUB

SELECT column_name(s) FROM table_name Gdzie ROWNUM

 -4
Author: Ritul Lakhtariya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-03 08:39:12