Топ-N в каждой группе
Вопрос
Как вывести трёх самых высокооплачиваемых сотрудников в каждом отделе? Что делать с равными зарплатами?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
ROW_NUMBER/RANK/DENSE_RANK с PARTITION BY department_id ORDER BY salary DESC
Фильтр по номеру во внешнем запросе или CTE: окно нельзя в WHERE
Выбор функции зависит от требований к равенству: ровно 3 строки или все с равной зарплатой
Для ROW_NUMBER добавить второй ключ сортировки для детерминизма
Альтернативы: LATERAL с LIMIT 3, коррелированный подзапрос
Индекс (department_id, salary DESC) ускоряет вариант с LATERAL
Что могут спросить следом
- Что вернёт DENSE_RANK <= 3, если у пятерых одинаковая зарплата?
- Как сделать это без оконных функций?
- Как это будет выполняться на 100 млн строк?
Разбор
Нумерую сотрудников внутри отдела оконной функцией: ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC, id). Фильтровать по ней в том же WHERE нельзя, оконные функции считаются позже, поэтому заворачиваю в подзапрос или CTE и снаружи пишу WHERE rn <= 3. Дальше вопрос к требованиям. Если нужно ровно три человека, беру ROW_NUMBER и второй ключ сортировки, чтобы результат был стабильным. Если при равенстве нужны все, кто делит третье место, беру RANK, а если нужны три разных уровня зарплаты, DENSE_RANK. Альтернатива, которая хорошо работает при индексе (department_id, salary DESC): JOIN LATERAL с ORDER BY salary DESC LIMIT 3 для каждого отдела, тогда база читает только по три строки из индекса на отдел.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Термины по теме
Ещё по теме «Оконные функции»
- Через сколько дней второй заказ
- Какие дубли удалить, оставив свежую запись
- Самый высоко- и низкооплачиваемый в отделе
- Самая длинная серия дней подряд
- Рост выручки к прошлому месяцу
- Скользящее среднее выручки за 3 дня
- Длинные перерывы между оплатами
- Разбиение кликов на сессии