Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle Analytic-Funktion für Mindestwert in der Gruppierung

Ich denke, dass die Funktion Rank() aus zwei Gründen nicht der richtige Weg ist.

Erstens ist es wahrscheinlich weniger effizient als eine auf Min() basierende Methode.

Der Grund dafür ist, dass die Abfrage beim Scannen der Daten eine geordnete Liste aller Gehälter pro Abteilung führen muss und der Rang dann später durch erneutes Lesen dieser Liste zugewiesen wird. Offensichtlich können Sie in Ermangelung von Indizes, die dafür genutzt werden können, keinen Rang zuweisen, bis das letzte Datenelement gelesen wurde, und die Pflege der Liste ist teuer.

Die Leistung der Rank()-Funktion hängt also von der Gesamtzahl der zu scannenden Elemente ab, und wenn die Anzahl ausreicht, dass die Sortierung auf die Festplatte übergeht, bricht die Leistung zusammen.

Dies ist wahrscheinlich effizienter:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

Diese Methode erfordert lediglich, dass die Abfrage pro Abteilung einen einzelnen Wert des bisher gefundenen Mindestwerts beibehält. Wenn ein neues Minimum angetroffen wird, wird der vorhandene Wert modifiziert, andernfalls wird der neue Wert verworfen. Die Gesamtzahl der Elemente, die im Speicher gehalten werden müssen, bezieht sich auf die Anzahl der Abteilungen, nicht auf die Anzahl der gescannten Zeilen.

Es könnte sein, dass Oracle einen Codepfad hat, um zu erkennen, dass der Rang in diesem Fall nicht wirklich berechnet werden muss, aber ich würde nicht darauf wetten.

Der zweite Grund, Rank() nicht zu mögen, ist, dass es nur die falsche Frage beantwortet. Die Frage lautet nicht "Welche Datensätze haben das Gehalt, das an erster Stelle steht, wenn die Gehälter pro Abteilung aufsteigend geordnet sind", sondern "Welche Datensätze haben das Gehalt, das das Minimum pro Abteilung ist". Das macht zumindest für mich einen großen Unterschied.