CodeRang
Типовые задачи

Вторая максимальная зарплата SQL: способы решения

Вторая максимальная зарплата SQL — задача, где сначала нужно решить, считаются ли одинаковые зарплаты одной позицией. Разберём решение через DENSE_RANK, сравним его с ROW_NUMBER и MAX и покажем, как тот же подход обобщается на N-е максимальное значение.

Обновлено · Команда SQL Arena

Что потренируете

  • Находить N-е по величине уникальное значение
  • Различать DENSE_RANK и ROW_NUMBER при равенствах
  • Строить топ-N отдельно внутри каждой группы
  • Понимать ограничения MAX и LIMIT/OFFSET
  • Проверять запрос на ничьих и коротких группах

Пример задачи в тренажёре

Так выглядит задача в SQL Arena: условие, редактор, результат и схема базы.

Пред.След.Случайная
ЗаданиеОтправкиAI Mentor
Найдите вторую зарплату в каждом отделе

Есть отделы и сотрудники. Для каждого отдела нужно вывести сотрудников со второй по величине уникальной зарплатой. Если такую зарплату получают несколько человек, должны попасть все. Верните department, employee и salary.

Запрос 1PostgreSQLv16
WITH ranked AS (
  SELECT d.name AS department, e.name AS employee, e.salary,
         DENSE_RANK() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS salary_rank
  FROM employees e JOIN departments d ON d.id = e.department_id
)
SELECT department, employee, salary
FROM ranked WHERE salary_rank = 2
ORDER BY department, employee;
Отправить
Результатdepartmentsemployees
Ответ принят

Как найти вторую максимальную зарплату SQL

Сначала строки делятся по отделам через PARTITION BY e.department_id. Это принципиально: рейтинг начинается заново в каждом отделе. Затем зарплаты сортируются по убыванию. Самая высокая получает ранг 1, следующая отличающаяся зарплата — ранг 2. Поэтому Sales с зарплатами 120000, 110000, 110000 и 90000 даёт ранги 1, 2, 2 и 3.

DENSE_RANK выбран из-за ничьих. Bob и Carol получают одинаковые 110000, и оба должны считаться обладателями второй зарплаты. ROW_NUMBER назначил бы им разные номера, например 2 и 3, хотя величина зарплаты у них одна. RANK сохранил бы ничью, но после неё оставил бы разрыв в нумерации; для поиска N-го уникального значения DENSE_RANK обычно выражает условие точнее.

CTE ranked нужен только для того, чтобы вынести вычисленный ранг в отдельный набор строк и затем отфильтровать salary_rank = 2. В том же SELECT нельзя надёжно использовать результат оконной функции в WHERE. Финальный ORDER BY делает результат однозначным: сначала отдел, затем имя сотрудника. В реальной задаче это также помогает стабильно сравнивать ожидаемый вывод.

Для второй максимальной зарплаты важно различать вторую строку и второе уникальное значение. DENSE_RANK() с сортировкой зарплаты по убыванию присваивает одинаковым зарплатам один ранг, поэтому ранг 2 соответствует второй отличающейся величине. ROW_NUMBER(), наоборот, нумерует строки отдельно и может разделить одинаковые значения между разными позициями. Если нужна только вторая уникальная зарплата без дополнительных колонок, задачу можно решать и через вложенные MAX. Для N-го максимального значения оконный подход удобнее обобщается: достаточно выбрать нужный ранг N.

SQLPostgreSQL v16
WITH ranked AS (
  SELECT d.name AS department, e.name AS employee, e.salary,
         DENSE_RANK() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS salary_rank
  FROM employees e JOIN departments d ON d.id = e.department_id
)
SELECT department, employee, salary
FROM ranked WHERE salary_rank = 2
ORDER BY department, employee;
Результат запроса
departmentemployeesalary
AnalyticsFrank125000
SalesBob110000
SalesCarol110000
SupportIvan85000
SupportJulia85000

Ошибки при поиске второй максимальной зарплаты

01

ROW_NUMBER вместо ранга значения

ROW_NUMBER нумерует строки, а не уникальные зарплаты. При двух одинаковых зарплатах одна строка может стать второй, а другая третьей. Такой запрос отвечает на вопрос «какая строка вторая после сортировки», но не всегда на вопрос «какая зарплата вторая по величине».

02

LIMIT 1 OFFSET 1 без DISTINCT

Для одной общей выборки часто пытаются отсортировать зарплаты и взять вторую строку. Если максимальная зарплата встречается дважды, OFFSET 1 вернёт ту же максимальную величину. Для N-го уникального значения сначала нужен DISTINCT или другая логика, учитывающая равенства.

03

Один рейтинг для всех отделов

Если убрать PARTITION BY, DENSE_RANK посчитает рейтинг по всей таблице сотрудников. Тогда salary_rank = 2 даст вторую зарплату компании целиком, а не вторую зарплату каждого отдела. Это одна из частых ловушек в формулировках «топ N в группе SQL».

Задачи по теме в тренажёре

Трек «Подготовка к собеседованию»

После этого примера полезно сменить формулировку, но оставить тот же принцип. В бесплатной задаче «Пилот рейса со вторым числом пассажиров» нужно распознать вторую позицию в другом наборе данных. Затем можно перейти к задаче «Вторая по величине зарплата», а после неё — к «Три самые высокие зарплаты в каждом отделе», где одиночная N-я позиция превращается в топ-N по каждой группе. Более сложные задачи добавляют временной порядок и необходимость определить, что именно считать «вторым» событием.

Справочник по теме

Подробные статьи с синтаксисом и примерами в справочнике SQL Arena.

Частые вопросы

Как найти вторую максимальную зарплату SQL?

Если нужна вторая уникальная зарплата, можно ранжировать значения через DENSE_RANK() по убыванию и выбрать ранг 2. Другой вариант — найти MAX среди зарплат, которые меньше общего максимума.

Как найти вторую максимальную зарплату при одинаковых значениях?

Если одинаковые зарплаты должны занимать одну позицию, удобно использовать DENSE_RANK. Все одинаковые значения получат один ранг, а следующая отличающаяся зарплата — следующий.

Чем DENSE_RANK отличается от ROW_NUMBER для зарплат?

DENSE_RANK присваивает одинаковым значениям одинаковый ранг. ROW_NUMBER выдаёт каждой строке отдельный номер, даже если зарплаты совпадают.

Как найти N-ю максимальную зарплату SQL?

Можно вычислить DENSE_RANK() по зарплате в порядке DESC и отфильтровать строки по нужному рангу N. Такой вариант естественно работает и для второй, и для любой другой N-й уникальной зарплаты.

Практика задач на вторую максимальную зарплату SQL

В SQL Arena можно решать задачи на ранжирование, N-е значение и топ-N с проверкой на скрытых данных. Если готовитесь к техническим вопросам, продолжите в треке «Подготовка к собеседованию»: там собраны задачи, где важно не только написать запрос, но и правильно разобрать условие. На бесплатном тарифе доступны 292 задачи без карты.

Решать задачи в SQL Arena