Мисля, че функцията Rank() не е начинът за това по две причини.
Първо, вероятно е по-малко ефективен от базиран на Min() метод.
Причината за това е, че заявката трябва да поддържа подреден списък на всички заплати за отдел, докато сканира данните, а рангът ще бъде присвоен по-късно чрез повторно четене на този списък. Очевидно при липса на индекси, които могат да се използват за това, не можете да зададете ранг, докато последният елемент от данни не бъде прочетен, а поддръжката на списъка е скъпа.
Така че производителността на функцията Rank() зависи от общия брой елементи, които трябва да бъдат сканирани, и ако броят е достатъчен, че сортирането се прехвърля на диска, производителността ще се срине.
Това вероятно е по-ефективно:
select dept,
emp,
salary
from
(
SELECT dept,
emp,
salary,
Min(salary) Over (Partition By dept) min_salary
FROM mytable
)
where salary = min_salary
/
Този метод изисква само заявката да поддържа една стойност за отдел от минималната стойност, срещана досега. Ако бъде открит нов минимум, съществуващата стойност се променя, в противен случай новата стойност се отхвърля. Общият брой елементи, които трябва да се съхраняват в паметта, е свързан с броя на отделите, а не с броя на сканираните редове.
Възможно е Oracle да има кодова пътека, за да разпознае, че рангът наистина не трябва да се изчислява в този случай, но не бих заложил на това.
Втората причина да не харесвате Rank() е, че той просто отговаря на грешен въпрос. Въпросът не е „Кои записи имат заплатата, която е първото класиране, когато заплатите по отдел са подредени във възходящ ред“, а „Кои записи имат заплатата, която е минималната за отдел“. Това поне за мен има голяма разлика.