Собесов

LeetCode SQL — Department Top Three Salaries (DENSE_RANK)

SQLTop-N per groupСложнаяMiddle

Условие

Таблицы:

  • Employee(id, name, salary, departmentId)
  • Department(id, name)

Для каждого отдела верните трёх сотрудников с топ-3 уникальных зарплат (если несколько человек получают одинаковую зарплату — все они идут в топ; топ-3 уникальных значений, не топ-3 строк).

Структура данных

Employee(id, name, salary, departmentId)
Department(id, name)

Выход: Department, Employee, Salary отсортированный по убыванию Salary внутри отдела.

Решение

DENSE_RANK() — стандартный приём

DENSE_RANK() нумерует равные значения одним рангом и не пропускает следующие — то что нужно для «топ-3 уникальных значений».

WITH ranked AS (
  SELECT
    d.name AS Department,
    e.name AS Employee,
    e.salary AS Salary,
    DENSE_RANK() OVER (PARTITION BY e.departmentId ORDER BY e.salary DESC) AS rnk
  FROM Employee e
  JOIN Department d ON d.id = e.departmentId
)
SELECT Department, Employee, Salary
FROM ranked
WHERE rnk <= 3
ORDER BY Department, Salary DESC;

Разница между RANK / DENSE_RANK / ROW_NUMBER

Зарплаты [100, 100, 80, 80, 60]:

Функция Ранги
ROW_NUMBER 1,2,3,4,5
RANK 1,1,3,3,5
DENSE_RANK 1,1,2,2,3

Здесь нужен DENSE_RANK ≤ 3: попадут все на ставках 100, 80, 60.

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

  1. RANK вместо DENSE_RANK. При двух людях с одинаковой топ-зарплатой RANK отдаст 1,1,3 — и третья позиция пропадёт (нет 2).
  2. ROW_NUMBER. Возьмёт ровно 3 строки — неверно, если двое имеют одну ставку.
  3. Departments без сотрудников. Не появятся в выходе — это ок по задаче.

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

DENSE_RANK() OVER (PARTITION BY departmentId ORDER BY salary DESC) <= 3. Не RANK, не ROW_NUMBER.

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

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

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