При разработке отчетов в системе 1С часто возникает задача агрегации данных по определенным периодам, например, по месяцам. Особенно это актуально для непериодических независимых регистров сведений, где дата хранится в обычном измерении или ресурсе. Разберем детально, как эффективно решить эту задачу, используя механизмы запросов и Систему компоновки данных (СКД).
Самый простой и производительный способ получить данные по месяцам — это использование функции НАЧАЛОПЕРИОДА непосредственно в тексте запроса. Если в вашем регистре есть измерение Дата, которое заполняется ежедневно, нам достаточно привести каждую дату к началу месяца и сгруппировать результат. Проанализируем пример кода, который решает эту задачу:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(РегистрДанных.Дата, МЕСЯЦ) КАК ПериодМесяц,
СУММА(РегистрДанных.Значение) КАК Показатель
ИЗ
РегистрСведений.ВашРегистр КАК РегистрДанных
ГДЕ
РегистрДанных.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(РегистрДанных.Дата, МЕСЯЦ)
УПОРЯДОЧИТЬ ПО
ПериодМесяц
В данном примере функция НАЧАЛОПЕРИОДА преобразует, например, «15.01.2022» и «20.01.2022» в единое значение «01.01.2022». Последующая группировка СГРУППИРОВАТЬ ПО объединяет все записи одного месяца в одну строку. Это гораздо эффективнее, чем пытаться делать выборку в цикле или связывать несколько наборов данных.
Иногда разработчики пытаются реализовать задачу через два разных запроса (набора данных) в СКД: первый запрос получает список дат, а второй — данные по конкретному периоду. Хотя в большинстве случаев лучше использовать один запрос, рассмотрим, как связать два набора данных, если этого требует логика:
Набор1), который возвращает список дат.Набор2) с параметрами &Дата1 и &Дата2.Набор1 как источник, а Набор2 как приемник.Важно: Помните, что связи наборов данных в СКД выполняются в цикле. Если в первом наборе будет много месяцев, СКД выполнит запрос ко второму набору столько же раз. Для больших объемов данных всегда предпочтительнее использовать один запрос с группировкой.
При использовании обычной группировки, если в каком-то месяце (например, в марте) не было записей в регистре, этот месяц просто не попадет в результат. Однако для красивого отчета часто требуется вывести все месяцы, даже с нулевыми значениями. Выясним, как это сделать в СКД:
Рассмотрим настройку «Дополнение периодов»:
ПериодМесяц.Период.Месяц.После этого СКД автоматически добавит недостающие строки для месяцев, в которых не было данных.
Проанализируем вопрос производительности. Поскольку мы работаем с непериодическим регистром сведений и фильтруем или группируем данные по измерению Дата, крайне важно обеспечить скорость работы запроса. Если в регистре накопится сотни тысяч записей, обычный запрос начнет тормозить.
Чтобы избежать этой проблемы, убедитесь в следующем:
Дата в конфигураторе установлено свойство «Индексировать».Так как регистр непериодический, у него нет виртуальной таблицы СрезПоследних. Если ваша задача — получить не сумму оборотов за месяц, а состояние данных на последнюю доступную дату каждого месяца, алгоритм усложняется. Посмотрим на примерную структуру такого запроса:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(т1.Дата, МЕСЯЦ) КАК Месяц,
МАКСИМУМ(т1.Дата) КАК МаксимальнаяДатаВМесяце
ПОМЕСТИТЬ ВТ_МаксДаты
ИЗ
РегистрСведений.ВашРегистр КАК т1
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(т1.Дата, МЕСЯЦ)
;
ВЫБРАТЬ
ВТ_МаксДаты.Месяц,
т2.Значение
ИЗ
ВТ_МаксДаты КАК ВТ_МаксДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ВашРегистр КАК т2
ПО ВТ_МаксДаты.МаксимальнаяДатаВМесяце = т2.Дата
В этом подходе мы сначала находим последнюю дату записи для каждого месяца, а затем соединяем этот результат с исходной таблицей регистра, чтобы получить значения, соответствующие этим датам.
Используя данные методы, вы сможете гибко настраивать отчеты по периодам, обеспечивая при этом высокую точность и производительность вашей системы на базе 1С.