Myślę, że funkcja Rank() nie jest drogą do tego, z dwóch powodów.
Po pierwsze jest prawdopodobnie mniej wydajna niż metoda oparta na Min().
Powodem jest to, że zapytanie musi zachować uporządkowaną listę wszystkich pensji na dział, ponieważ skanuje dane, a ranga zostanie przypisana później poprzez ponowne przeczytanie tej listy. Oczywiście w przypadku braku indeksów, które można wykorzystać do tego celu, nie można przypisać rankingu, dopóki ostatni element danych nie zostanie odczytany, a konserwacja listy jest droga.
Tak więc wydajność funkcji Rank() zależy od łącznej liczby skanowanych elementów, a jeśli liczba jest wystarczająca, aby sortowanie zostało rozlane na dysk, wydajność zostanie zwinięta.
Jest to prawdopodobnie bardziej efektywne:
select dept,
emp,
salary
from
(
SELECT dept,
emp,
salary,
Min(salary) Over (Partition By dept) min_salary
FROM mytable
)
where salary = min_salary
/
Ta metoda wymaga jedynie, że zapytanie utrzymać pojedynczą wartość na wydziale minimalnej wartości spotykanych do tej pory. Jeśli napotkane zostanie nowe minimum, wówczas zmieni się istniejąca wartość, w przeciwnym razie nowa wartość zostanie odrzucona. Łączna liczba elementów, które muszą być przechowywane w pamięci, zależy od liczby działów, a nie od liczby przeskanowanych wierszy.
Może się zdarzyć, że Oracle ma ścieżkę do kodu, aby rozpoznać, że Rank nie musi być w tym przypadku wyliczany, ale nie postawiłbym na to.
Drugą przyczyną niechęci do Rang() jest odpowiedź na niewłaściwe pytanie. Pytanie nie brzmi: "Które rekordy mają pensję, która jest pierwszym rankingiem, kiedy pensje na wydział są sortowane rosnąco", jest to "Które rekordy mają wynagrodzenie, które jest minimalne dla każdego działu". Co najmniej ma dla mnie dużą różnicę.
Dziękuję David. Po rozważeniu jego zalet, refakturowałem do twojego rozwiązania. –