Содержание статьи

В большинстве аналитических и транзакционных систем даты хранятся в типах DATE, TIMESTAMP или их производных, но сами по себе эти значения редко используются напрямую. Гораздо чаще требуется получить номер или название месяца, чтобы построить отчёт по продажам за март, отфильтровать записи за конкретный период или сгруппировать данные по календарным интервалам. SQL предоставляет для этого отдельные функции и операторы, и их синтаксис зависит от используемой СУБД.
Например, в PostgreSQL и Oracle используется конструкция EXTRACT(MONTH FROM дата), тогда как MySQL предлагает функцию MONTH(дата), а SQL Server – DATEPART(month, дата). Эти вызовы возвращают целое число от 1 до 12, что удобно для фильтрации и арифметических операций, но для пользовательских отчётов часто требуется преобразовать результат в текстовое название месяца через форматирование даты.
Ошибки при работе с месяцами возникают из-за различий в типах данных, часовых поясах и строковых представлениях дат. Если поле имеет тип VARCHAR, его нужно предварительно привести к DATE или TIMESTAMP, иначе функции извлечения вернут неверный результат или вызовут исключение. При агрегации по месяцам важно также учитывать год, чтобы не смешивать, например, январь 2024 и январь 2025 в одной группе.
Грамотное извлечение месяца – это не только выбор нужной функции, но и контроль формата входных данных, корректная обработка NULL и понимание того, что именно требуется: числовой индекс, текстовое имя или компонент даты для группировки. От этих деталей зависит, насколько предсказуемо будет работать запрос в отчётах и бизнес-логике.
Получение номера месяца из поля DATE с помощью EXTRACT

Функция EXTRACT применяется в PostgreSQL, Oracle и ряде других СУБД для выборки отдельных компонентов даты из значений типа DATE и TIMESTAMP. Для получения месяца используется синтаксис EXTRACT(MONTH FROM дата), который возвращает целое число от 1 до 12, где 1 соответствует январю, а 12 – декабрю. Это делает результат пригодным для фильтрации, сортировки и числовых вычислений.
При работе с полями типа TIMESTAMP WITH TIME ZONE важно помнить, что EXTRACT использует уже нормализованное значение времени, поэтому смена часового пояса может изменить календарную дату и, как следствие, номер месяца. Если отчёты строятся по локальному времени, дату следует предварительно привести к нужной зоне с помощью AT TIME ZONE, а уже затем извлекать месяц.
В выражениях фильтрации EXTRACT удобно комбинировать с другими условиями. Например, чтобы выбрать все записи за апрель, достаточно использовать сравнение EXTRACT(MONTH FROM order_date) = 4. Для выборки только текущего месяца можно сравнивать результат с EXTRACT(MONTH FROM CURRENT_DATE), что избавляет от жёстко заданных чисел и упрощает поддержку запросов.
При агрегации данных по месяцам следует учитывать и год, поскольку EXTRACT(MONTH) не различает одинаковые месяцы разных лет. Корректная группировка строится через сочетание EXTRACT(YEAR FROM дата) и EXTRACT(MONTH FROM дата), что предотвращает объединение, например, всех январей в одну категорию и сохраняет точность временных разрезов.
Извлечение месяца в MySQL через функцию MONTH()
- для выборки всех записей за июль применяется выражение MONTH(order_date) = 7
- для работы с текущим месяцем используется MONTH(CURDATE()) или MONTH(NOW())
- для вычисления разницы месяцев между двумя датами удобнее комбинировать MONTH() с YEAR()
Если поле хранит дату в виде строки, его необходимо привести к типу даты, иначе MONTH() вернёт NULL или некорректное значение. Для этого применяется STR_TO_DATE(строка, формат), после чего функция обрабатывает результат как обычный DATE.
- преобразовать строку к дате через STR_TO_DATE
- передать полученное значение в MONTH()
- использовать числовой результат в фильтре или группировке
При агрегации данных по месяцам в MySQL нельзя ограничиваться только MONTH(), так как январь разных лет будет объединён. Для корректных отчётов применяется связка YEAR(дата) и MONTH(дата) в секции GROUP BY, что гарантирует разделение периодов по календарным годам.
Определение месяца в PostgreSQL с использованием date_part
В PostgreSQL для извлечения месяца из даты применяется функция date_part, принимающая имя компонента и значение типа DATE или TIMESTAMP. Вызов date_part(‘month’, order_date) возвращает числовое значение от 1 до 12 в формате double precision, поэтому при необходимости его можно привести к целому типу через ::int для использования в индексируемых сравнениях и вычислениях.
При работе с временными метками, содержащими часовую зону, date_part опирается на локальное представление времени. Если данные хранятся в TIMESTAMPTZ, а отчёты строятся по другому региону, сначала выполняется преобразование через AT TIME ZONE, и только затем извлекается месяц, что предотвращает смещение даты на границе месяцев.
Для фильтрации записей за конкретный месяц удобно использовать выражение date_part(‘month’, created_at) = 10, а для динамических условий – сравнение с date_part(‘month’, current_date). Такой подход избавляет от жёстко заданных дат и поддерживает корректную работу запросов при смене календарного периода.
При группировке данных date_part применяется совместно с извлечением года, например date_part(‘year’, дата), поскольку одинаковые месяцы разных лет иначе будут объединены. Использование обеих компонент в GROUP BY обеспечивает точное разделение временных интервалов и предсказуемые итоги агрегаций.
Получение месяца из даты в SQL Server через DATEPART

В SQL Server извлечение месяца выполняется через функцию DATEPART, где в качестве первого аргумента указывается компонент даты, а вторым передаётся поле или выражение. Для месяца используется вариант DATEPART(month, order_date), который возвращает целое число от 1 до 12, полностью совместимое с числовыми операциями и условиями фильтрации.
При работе с типами datetime, datetime2 и date функция обрабатывает значение без преобразований, но для строковых представлений требуется предварительное приведение через CAST или CONVERT. Неправильный формат строки приведёт к ошибке преобразования, поэтому при импорте данных из текстовых источников следует явно задавать стиль даты.
Для выборки записей за конкретный месяц применяется условие вида DATEPART(month, created_at) = 5. Если требуется работать с текущим месяцем, вместо числа используется DATEPART(month, GETDATE()), что позволяет запросу автоматически подстраиваться под календарную дату сервера.
В задачах агрегации DATEPART используется вместе с извлечением года через DATEPART(year, дата). Такое сочетание в GROUP BY исключает объединение одинаковых месяцев разных лет и сохраняет точность временных отчётов, особенно при анализе данных за несколько периодов.
Извлечение названия месяца из даты с помощью форматирования

- в PostgreSQL применяется to_char(дата, ‘Month’) для полного названия и to_char(дата, ‘Mon’) для сокращённого
- в MySQL используется DATE_FORMAT(дата, ‘%M’) для полного и DATE_FORMAT(дата, ‘%b’) для краткого варианта
- в SQL Server форматирование выполняется через FORMAT(дата, ‘MMMM’) или DATENAME(month, дата)
Язык возвращаемых названий зависит от локали сервера или текущей сессии. В PostgreSQL его задаёт параметр lc_time, в MySQL – системная локаль, а в SQL Server – региональные настройки. Для многоязычных приложений это означает, что один и тот же запрос может выдавать «March» или «Март» без изменения кода.
- установить нужную локаль на уровне соединения или базы
- применить функцию форматирования с шаблоном месяца
- использовать полученную строку в отчётах или группировках
При агрегации по названиям месяцев всегда следует дополнительно учитывать год, так как строковые значения не различают периоды разных лет и могут привести к объединению одноимённых месяцев в одну категорию.
Работа с месяцем при группировке дат в запросах
Группировка по месяцам в SQL требует использования функции извлечения месяца (EXTRACT, MONTH(), DATEPART) вместе с годом, иначе одинаковые месяцы разных лет объединятся. Например, для корректной агрегации продаж за январь 2023 и январь 2024 необходимо в GROUP BY включать YEAR(дата) и месяц одновременно.
Для построения отчётов и графиков рекомендуется создавать вычисляемые столбцы с номером месяца или строковым представлением месяца. Это позволяет:
- использовать числовой месяц для сортировки по календарю
- использовать текстовое название месяца для отображения в отчётах
- объединять данные по месяцам без потери информации о годе
При сложных временных фильтрах удобно применять динамические выражения, например EXTRACT(MONTH FROM CURRENT_DATE), чтобы запрос автоматически выбирал текущий месяц. Для месячной агрегации с дополнительными условиями лучше использовать CASE или подзапросы, чтобы исключить пропуски месяцев в итоговой выборке.
В MySQL, PostgreSQL и SQL Server числовые значения месяца позволяют легко рассчитывать промежутки между месяцами, строить скользящие отчёты и ранжировать данные. Для визуализации рекомендуется дополнительно формировать строковое название месяца, чтобы итоговые графики и таблицы были читаемыми и соответствовали календарной последовательности.
Обработка NULL и некорректных дат при получении месяца
При извлечении месяца из даты важно учитывать наличие NULL и некорректных значений, чтобы запрос не возвращал ошибки и результаты были точными. В SQL любые функции извлечения месяца (EXTRACT, MONTH(), DATEPART) возвращают NULL, если входное поле пустое или содержит неправильный формат. Для предотвращения этого применяются проверки и преобразования.
Варианты обработки ошибок:
| Сценарий | Решение |
|---|---|
| Поле даты может быть NULL | Использовать COALESCE(дата, ‘2000-01-01’) или условие WHERE дата IS NOT NULL |
| Дата хранится в строковом формате | Преобразовать с помощью STR_TO_DATE в MySQL или TO_DATE в PostgreSQL; некорректные строки приводят к NULL |
| Некорректные диапазоны или переполнения | Применять TRY_CAST или TRY_CONVERT в SQL Server, чтобы некорректные значения не ломали запрос |
| Агрегация с возможными NULL | Использовать COALESCE или фильтр WHERE MONTH(дата) IS NOT NULL для корректной группировки |
Контроль типов данных и проверка формата перед вызовом функций извлечения месяца позволяет избежать неожиданных NULL в результатах и обеспечивает точность фильтров и агрегатов при работе с большими объёмами данных.
Вопрос-ответ:
Как получить номер месяца из даты в PostgreSQL?
В PostgreSQL для извлечения месяца из поля типа DATE или TIMESTAMP используется функция EXTRACT или date_part. Например, выражение EXTRACT(MONTH FROM order_date) вернёт число от 1 до 12. Если нужно целое значение для сортировки или фильтрации, можно привести результат к типу int через ::int. При работе с часовыми зонами рекомендуется предварительно привести дату к нужной зоне через AT TIME ZONE, чтобы корректно определить месяц.
Как в MySQL извлечь месяц из строки с датой?
Если дата хранится как строка, её нужно сначала преобразовать в формат DATE с помощью функции STR_TO_DATE(строка, формат). После этого можно применять MONTH(), чтобы получить число месяца. Например: MONTH(STR_TO_DATE(‘2026-01-03’, ‘%Y-%m-%d’)) вернёт 1. Без преобразования MySQL вернёт NULL или вызовет ошибку, если формат строки не соответствует ожидаемому шаблону.
Можно ли группировать данные по месяцу без учёта года?
Да, это возможно, но нужно понимать последствия. Функции извлечения месяца возвращают только номер от 1 до 12, поэтому при группировке без учёта года все одинаковые месяцы разных лет будут объединены. Для точной агрегации рекомендуется включать и год: например, GROUP BY EXTRACT(YEAR FROM дата), EXTRACT(MONTH FROM дата). Это позволит отличать январь 2023 от января 2024 и получать корректные суммарные значения.
Как обрабатывать NULL и некорректные даты при извлечении месяца?
Функции извлечения месяца возвращают NULL для пустых или некорректных значений. Чтобы избежать ошибок, используют проверки и приведение типов. В MySQL можно применять STR_TO_DATE для строк, в SQL Server — TRY_CAST или TRY_CONVERT. Также рекомендуется фильтровать записи с NULL через WHERE дата IS NOT NULL или заменять их через COALESCE на безопасное значение, чтобы агрегатные функции и фильтры работали корректно.
