Как автоматически получить максимальный квартал для каждого года в 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 можно за пару минут с помощью оконных функций или группировки. Откажитесь от ручного перечисления - используйте универсальные конструкции, которые адаптируются к любым изменениям данных.

    Часто задаваемые вопросы