Как в запросе и встроенном языке 1С сгруппировать данные по месяцам и годам?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При построении отчетов с детализацией по месяцам за период в несколько лет разработчики часто сталкиваются с задачей разделения одинаковых месяцев разных лет (например, март 2023 и март 2024 года). Если сгруппировать данные только по функции МЕСЯЦ(Период), данные за разные годы объединятся в один общий месяц. Разберем основные и наиболее эффективные способы корректной группировки, нумерации и форматирования периодов в языке запросов, СКД и программном коде 1С.

Способ 1. Общепринятый стандарт: функция НАЧАЛОПЕРИОДА в запросе

Рассмотрим самый надежный, производительный и рекомендуемый стандарт платформы 1С для группировки данных по месяцам. Функция НАЧАЛОПЕРИОДА приводит любую дату к первому числу соответствующего месяца со временем 00:00:00.

Посмотрим на практический пример запроса к регистру накопления:


ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) КАК МесяцПериода,
    Продажи.Номенклатура КАК Номенклатура,
    СУММА(Продажи.СуммаОборот) КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаКонца, Авто, ) КАК Продажи
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ),
    Продажи.Номенклатура
УПОРЯДОЧИТЬ ПО
    МесяцПериода

Проанализируем преимущества этого подхода:

  1. Сохранение типа данных: Поле остается полноценным типом Дата, что сохраняет встроенные механизмы сортировки и фильтрации.
  2. Корректная хронология: Март 2023 года (01.03.2023 00:00:00) автоматически будет меньше марта 2024 года (01.03.2024 00:00:00), упорядочивание сработает идеально.
  3. Гибкость представления: Преобразование даты в читаемый вид («Март 2024 г.», «03.2024» и т.д.) выполняется на уровне вывода в отчет или макет, не усложняя текст запроса.

Способ 2. Использование возможностей виртуальных таблиц регистров

Если источником данных является виртуальная таблица регистра (например, Обороты или ОстаткиИОбороты), платформа 1С предоставляет встроенные средства группировки периодов.

Разберем два варианта настройки периодичности:

  1. Явное указание периодичности: В параметрах виртуальной таблицы укажем периодичность Месяц. В этом случае системное поле Период уже будет представлять собой дату начала месяца.
  2. Периодичность «Авто»: При выборе значения Авто в списке доступных полей виртуальной таблицы появляются готовые поля: ПериодСекунда, ПериодДень, ПериодМесяц, ПериодКвартал, ПериодГод. Достаточно выбрать ПериодМесяц без использования дополнительных функций.

ВЫБРАТЬ
    Продажи.ПериодМесяц КАК ПериодМесяц,
    Продажи.Номенклатура КАК Номенклатура,
    Продажи.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаКонца, Авто, ) КАК Продажи

Способ 3. Вычисление числового идентификатора периода (YYYYMM)

В некоторых задачах (например, для экспорта данных, интеграций через JSON/XML или специфических вычислений) требуется получить период в виде целого числа. Разберем, как правильно составить формулу и почему частые решения на форумах содержат ошибку.

Ошибочный вариант: МЕСЯЦ(Период) * 10000 + ГОД(Период). При такой формуле март 2024 года превратится в число 32024, а декабрь 2023 года — в 122023. При сортировке декабрь 2023 окажется позже марта 2024, что нарушит порядок данных.

Правильный вариант: Формирование числа в формате ГГГГММ:


ВЫБРАТЬ
    ГОД(Затраты.Период) * 100 + МЕСЯЦ(Затраты.Период) КАК КодПериодаЧислом,
    СУММА(Затраты.Сумма) КАК Сумма
ИЗ
    РегистрНакопления.Затраты КАК Затраты
СГРУППИРОВАТЬ ПО
    ГОД(Затраты.Период) * 100 + МЕСЯЦ(Затраты.Период)

В данном случае март 2024 года станет числом 202403, а декабрь 2023 — 202312. Числовая сортировка полностью совпадает с хронологической.

Способ 4. Получение абсолютного номера месяца через РАЗНОСТЬДАТ

Если требуется получить сквозной порядковый номер месяца с начала летоисчисления или от конкретной точки отсчета, воспользуемся функцией РАЗНОСТЬДАТ.


ВЫБРАТЬ
    РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), Затраты.Период, МЕСЯЦ) КАК НомерМесяцаОтНачала,
    СУММА(Затраты.Сумма) КАК Сумма
ИЗ
    РегистрНакопления.Затраты КАК Затраты
СГРУППИРОВАТЬ ПО
    РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), Затраты.Период, МЕСЯЦ)

Обратим внимание на производительность: не рекомендуется использовать вычисляемые выражения с РАЗНОСТЬДАТ, МЕСЯЦ или ГОД в секции ГДЕ (условиях фильтрации) запроса. Такие конструкции приводят к блокировке использования индексов СУБД и вызывают полное сканирование таблицы (Table Scan). Для фильтрации всегда передавайте точные граничные даты: Период МЕЖДУ &ДатаНачала И &ДатаКонца.

Способ 5. Настройка группировок и формата в Системе компоновки данных (СКД)

Если отчет разрабатывается с использованием СКД, писать дополнительные вычисления в тексте запроса не требуется.

  1. В запросе выбираем исходное детальное поле Период.
  2. В настройках структуры отчета добавляем группировку по полю Период и в типе дополнения периода выбираем Месяц.
  3. На вкладке Наборы данных или в Условном оформлении настраиваем формат отображения даты в поле Формат:
    1. ДФ='ММММ гггг' — отобразит дату в виде «Март 2024».
    2. ДФ=MM.yyyy — отобразит дату в виде «03.2024».
    3. ДФ='кв. К гггг' — отобразит дату в виде «кв. 1 2024».

Способ 6. Работа с месяцами во встроенном языке 1С

В программном коде конфигурации для работы с месяцами и датами предусмотрен богатый набор встроенных функций платформы:


// Приведение даты к первому числу месяца
ДатаМесяца = НачалоМесяца(ТекущаяДата());

// Форматирование для вывода пользователю
ПредставлениеПериода = Формат(ТекущаяДата(), "ДФ='ММММ гггг'"); // Например, "Март 2024"

// Расчет количества месяцев между двумя датами
КоличествоМесяцев = (Год(ДатаКонца) - Год(ДатаНачала)) * 12 + (Месяц(ДатаКонца) - Месяц(ДатаНачала));

// Смещение даты на заданное число месяцев
СледующийПериод = ДобавитьМесяц(ДатаМесяца, 1);

Подведем итог: для отчетов и группировок в запросах всегда отдавайте предпочтение функции НАЧАЛОПЕРИОДА(Период, МЕСЯЦ) с последующим форматированием в представлении. Это гарантирует максимальную производительность базы данных и корректное хронологическое упорядочивание записей.

← На главную