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

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

При разработке отчетов в системе 1С часто возникает задача агрегации данных по определенным периодам, например, по месяцам. Особенно это актуально для непериодических независимых регистров сведений, где дата хранится в обычном измерении или ресурсе. Разберем детально, как эффективно решить эту задачу, используя механизмы запросов и Систему компоновки данных (СКД).

Группировка данных средствами языка запросов

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


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

В данном примере функция НАЧАЛОПЕРИОДА преобразует, например, «15.01.2022» и «20.01.2022» в единое значение «01.01.2022». Последующая группировка СГРУППИРОВАТЬ ПО объединяет все записи одного месяца в одну строку. Это гораздо эффективнее, чем пытаться делать выборку в цикле или связывать несколько наборов данных.

Связь наборов данных в СКД для передачи параметров

Иногда разработчики пытаются реализовать задачу через два разных запроса (набора данных) в СКД: первый запрос получает список дат, а второй — данные по конкретному периоду. Хотя в большинстве случаев лучше использовать один запрос, рассмотрим, как связать два набора данных, если этого требует логика:

  1. Создадим первый набор данных (Набор1), который возвращает список дат.
  2. Создадим второй набор данных (Набор2) с параметрами &Дата1 и &Дата2.
  3. Перейдем на вкладку «Связи наборов данных».
  4. Укажем Набор1 как источник, а Набор2 как приемник.
  5. В колонке «Параметры связи» укажем соответствие: поле даты из первого набора должно передаваться в параметры второго набора.

Важно: Помните, что связи наборов данных в СКД выполняются в цикле. Если в первом наборе будет много месяцев, СКД выполнит запрос ко второму набору столько же раз. Для больших объемов данных всегда предпочтительнее использовать один запрос с группировкой.

Решение проблемы отсутствующих периодов («дырок»)

При использовании обычной группировки, если в каком-то месяце (например, в марте) не было записей в регистре, этот месяц просто не попадет в результат. Однако для красивого отчета часто требуется вывести все месяцы, даже с нулевыми значениями. Выясним, как это сделать в СКД:

Рассмотрим настройку «Дополнение периодов»:

  1. В наборе данных СКД выберите поле ПериодМесяц.
  2. В колонке «Роль» укажите, что это поле является периодом, и установите тип Период.
  3. В настройках отчета (вкладка «Настройки»), выберите группировку по этому полю.
  4. На вкладке «Дополнительные настройки» для этой группировки найдите свойство «Тип дополнения» и установите значение Месяц.
  5. Укажите границы дополнения (например, параметры начала и конца периода отчета).

После этого СКД автоматически добавит недостающие строки для месяцев, в которых не было данных.

Оптимизация: Индексирование измерения Даты

Проанализируем вопрос производительности. Поскольку мы работаем с непериодическим регистром сведений и фильтруем или группируем данные по измерению Дата, крайне важно обеспечить скорость работы запроса. Если в регистре накопится сотни тысяч записей, обычный запрос начнет тормозить.

Чтобы избежать этой проблемы, убедитесь в следующем:

Получение состояния на конец месяца (аналог Среза последних)

Так как регистр непериодический, у него нет виртуальной таблицы СрезПоследних. Если ваша задача — получить не сумму оборотов за месяц, а состояние данных на последнюю доступную дату каждого месяца, алгоритм усложняется. Посмотрим на примерную структуру такого запроса:


ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(т1.Дата, МЕСЯЦ) КАК Месяц,
    МАКСИМУМ(т1.Дата) КАК МаксимальнаяДатаВМесяце
ПОМЕСТИТЬ ВТ_МаксДаты
ИЗ
    РегистрСведений.ВашРегистр КАК т1
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(т1.Дата, МЕСЯЦ)
;

ВЫБРАТЬ
    ВТ_МаксДаты.Месяц,
    т2.Значение
ИЗ
    ВТ_МаксДаты КАК ВТ_МаксДаты
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ВашРегистр КАК т2
    ПО ВТ_МаксДаты.МаксимальнаяДатаВМесяце = т2.Дата

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

Используя данные методы, вы сможете гибко настраивать отчеты по периодам, обеспечивая при этом высокую точность и производительность вашей системы на базе 1С.

← На главную