Как автоматически получить максимальный квартал для каждого года в SQL
При работе с данными, содержащими год и квартал, часто требуется для каждого года отобрать только последний (максимальный) квартал. Ручное перечисление значений через WHERE Год_Квартал IN (...) - трудоёмкий и негибкий подход. В этой статье разберём эффективные способы автоматизации такой выборки с помощью оконных функций и подзапросов.
Проблема ручного перебора кварталов
Предположим, у вас есть таблица с данными за несколько лет. Вручную прописывать WHERE Год_Квартал IN ('2023.4', '2024.2') неудобно: при каждом добавлении нового года или изменении данных придётся править запрос. К тому же такой код сложно поддерживать и масштабировать.
Решение с оконной функцией ROW_NUMBER()
Самый универсальный способ - использовать оконную функцию ROW_NUMBER() с партицией по году и сортировкой по кварталу по убыванию. Затем во внешнем запросе отфильтровать строки с номером rn = 1.
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Год ORDER BY Квартал DESC) AS rn
FROM ваша_таблица
)
SELECT Год, Квартал, Показатели
FROM ranked
WHERE rn = 1;Этот запрос автоматически находит последний квартал каждого года, независимо от того, сколько кварталов присутствует в данных.
Альтернатива: подзапрос с MAX()
Если вам не нужны остальные столбцы, можно применить группировку с функцией MAX():
SELECT Год, MAX(Квартал) AS Последний_квартал
FROM ваша_таблица
GROUP BY Год;Такой вариант возвращает только год и максимальный квартал, без детальных показателей. Для получения полной записи его нужно объединить с исходной таблицей через JOIN.
Сравнение подходов
- ROW_NUMBER() - гибкость, можно получить любые столбцы, работает в PostgreSQL, MySQL 8+, SQL Server, Oracle, SQLite 3.25+.
- MAX() + GROUP BY - простой, но требует дополнительного соединения для извлечения остальных данных.
- DISTINCT ON (PostgreSQL) - лаконичная альтернатива:
SELECT DISTINCT ON (Год) * FROM ваша_таблица ORDER BY Год, Квартал DESC;
Что делать, если квартал хранится в формате '2023.4'?
Если год и квартал объединены в одном поле, сначала разделите их с помощью строковых функций, а затем примените оконную функцию:
WITH parsed AS (
SELECT *,
CAST(SUBSTRING(Год_Квартал, 1, 4) AS INTEGER) AS Год,
CAST(SUBSTRING(Год_Квартал, 6, 1) AS INTEGER) AS Квартал
FROM ваша_таблица
),
ranked AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Год ORDER BY Квартал DESC) AS rn
FROM parsed
)
SELECT Год_Квартал, Показатели
FROM ranked
WHERE rn = 1;Этот приём позволяет обрабатывать данные без предварительной нормализации.
Заключение
Автоматизировать выборку максимального квартала для каждого года в SQL можно за пару минут с помощью оконных функций или группировки. Откажитесь от ручного перечисления - используйте универсальные конструкции, которые адаптируются к любым изменениям данных.