Собесов

Aafreen29/SQL-Interview-Prep: топ-3 зарплат в каждом отделе

SQLОконные функцииСредняяMiddle

Условие

Из таблиц employee(id, name, salary, dept_id) и department(id, name) выведите топ-3 сотрудников по зарплате в каждом отделе. При равенстве зарплат сотрудники с одинаковой суммой считаются разделяющими место.

Решение

Подход

Оконная функция DENSE_RANK() партиционирована по отделу и упорядочена по зарплате DESC. Все сотрудники с rank ≤ 3 попадают в топ-3. Это даёт честное «топ-3 уникальных уровней зарплаты», даже если на одном уровне несколько человек.

Реализация

WITH ranked AS (
    SELECT
        d.name AS dept,
        e.name AS employee,
        e.salary,
        DENSE_RANK() OVER (
            PARTITION BY e.dept_id
            ORDER BY e.salary DESC
        ) AS rnk
    FROM employee e
    JOIN department d ON d.id = e.dept_id
)
SELECT dept, employee, salary
FROM ranked
WHERE rnk <= 3
ORDER BY dept, salary DESC;

Подводные камни

  1. RANK vs DENSE_RANK vs ROW_NUMBER — критически разные результаты. RANK пропустит номера (1, 1, 3 — и третьего по величине нет), ROW_NUMBER оставит ровно 3 строки даже при ничьих и потеряет претендентов. На «топ-N разных уровней» брать DENSE_RANK.
  2. Отделы с < 3 сотрудниками — попадут целиком; это правильно.
  3. JOIN с department: если у отдела нет сотрудников, его не будет в выводе. Если нужно показать пустые отделы — LEFT JOIN, начиная с department.
  4. На больших таблицах оконка по огромному отделу дорогая; индекс (dept_id, salary DESC) ускорит.

Эталонный ответ

DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) <= 3. RANK пропускает номера, ROW_NUMBER обрубает ничьи — в задаче «топ-N уровней» используйте именно DENSE_RANK.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти