Как вывести вторую по величине зарплату в SQL?
Популярная задача с собеседований: нужно найти вторую по величине зарплату в таблице сотрудников. Просто MAX даёт первую. Как достать именно второе значение, и что если есть одинаковые максимумы?
2 ответа
Есть несколько способов, разберём самые надёжные.
Способ 1 — через DISTINCT, ORDER BY и OFFSET (Postgres/MySQL):
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
DISTINCT убирает повторы зарплат, сортировка по убыванию, OFFSET 1 пропускает самую большую, LIMIT 1 берёт следующую — это и есть вторая по величине.
Способ 2 — через подзапрос (работает почти везде):
SELECT MAX(salary)
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
Читается красиво: «максимум среди тех, кто меньше общего максимума».
Способ 3 — оконная функция DENSE_RANK (если N-я по величине):
SELECT salary FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) t
WHERE rnk = 2;
Главная ловушка — одинаковые зарплаты. Если максимум 100000 получают двое, то «вторая» зависит от трактовки. DISTINCT и подход с подзапросом считают второе уникальное значение. DENSE_RANK — то же (ранг 2 — это второе по величине значение, а не вторая строка). А вот ROW_NUMBER дал бы «вторую строку», что для дублей не то. Поэтому для «второй зарплаты» берите DISTINCT или DENSE_RANK, а не ROW_NUMBER.
Не забудьте про пограничный случай: что вернуть, если в таблице всего одна зарплата (или все одинаковые)? Варианты со LIMIT/OFFSET и DENSE_RANK вернут пустой результат, а вариант MAX(... WHERE salary < MAX) вернёт NULL (одна строка). На собеседовании уточните у интервьюера, какое поведение ожидается — это часто и есть проверяемый момент.