Условие
Из таблицы employee(id, salary) найдите вторую по величине уникальную зарплату. Если такой нет (все зарплаты одинаковые или сотрудник один), верните NULL.
Решение
Подход
Тут пять разных типичных решений и каждое имеет нюанс с обработкой случая «второй разной зарплаты нет».
Реализация
-- 1) Подзапрос с MAX < MAX (классика, обрабатывает NULL автоматически)
SELECT MAX(salary) AS second_highest
FROM employee
WHERE salary < (SELECT MAX(salary) FROM employee);
-- 2) LIMIT/OFFSET по DISTINCT
SELECT DISTINCT salary AS second_highest
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
-- Минус: если второй разной нет — пусто, а не NULL.
-- 3) DENSE_RANK (универсально для k-й по величине)
SELECT salary AS second_highest
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) t
WHERE rnk = 2
LIMIT 1;
-- 4) Гарантия NULL вместо пустого результата
SELECT (
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1
) AS second_highest;Подводные камни
RANKvsDENSE_RANKvsROW_NUMBER: при одинаковых зарплатахRANKпропустит номера (1, 1, 3 — и второй по величине отсутствует),ROW_NUMBERназначит уникальные номера и вторая зарплата может оказаться той же, что и первая. Нужен именноDENSE_RANKилиDISTINCT salary.- «Пусто» vs
NULL: вариант сLIMIT/OFFSETвозвращает пустой набор, а интервьюер обычно ждёт строку со значениемNULL. Оборачивайте в скалярный подзапрос (SELECT (...)). - Дубликаты зарплат. Без
DISTINCTилиDENSE_RANKвторая «по строке» — это часто первая по величине. Обязательно ищите по уникальным значениям. - N-я по величине. Решение через
DENSE_RANKлегко обобщается до n-й:WHERE rnk = N.
Эталонный ответ
SELECT MAX(salary) FROM employee WHERE salary < (SELECT MAX(salary) FROM employee) или DENSE_RANK() OVER (ORDER BY salary DESC) = 2. Оба корректно обрабатывают дубликаты и при отсутствии второй зарплаты возвращают NULL.