Я думаю, что функция 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 () заключается в том, что он просто отвечает на неправильный вопрос. Вопрос не в том, «Какая запись имеет зарплату, которая является первой в рейтинге, когда зарплата по отделу упорядочена по возрастанию», а в том, «Какая запись имеет минимальную зарплату на отдел». Это имеет большое значение для меня, по крайней мере.