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)

War es hilfreich?

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top