При разработке отчетов на системе компоновки данных (СКД) в 1С часто возникает архитектурная задача: необходимо рассчитать агрегатное значение на одном из верхних уровней группировки на основании результатов самого нижнего уровня. При этом стандартное суммирование по детальным записям не подходит, а промежуточные группировки не должны влиять на результат вычислений.
В этой статье мы подробно разберем, как решить эту задачу с помощью встроенных функций СКД ВычислитьВыражениеСГруппировкойМассив и ВычислитьВыражениеСГруппировкойТаблицаЗначений, рассмотрим правильную настройку ресурсов и альтернативный (более производительный) метод решения задачи через запрос.
Проанализируем классическую многоуровневую структуру отчета:
Наша цель — рассчитать некоторый показатель (например, максимум или среднее) на уровне «Характеристика», а затем сложить эти полученные значения на уровне «Производитель», полностью проигнорировав промежуточные группы номенклатуры и саму номенклатуру.
Функция ВычислитьВыражениеСГруппировкойМассив является мощным инструментом СКД. Она выполняет указанное выражение для записей выбранной группировки, обходя их, собирает результаты во временный массив в оперативной памяти, а затем позволяет применить к этому массиву внешнюю агрегатную функцию на более высоком уровне компоновки.
Рассмотрим синтаксис этой функции:
ВычислитьВыражениеСГруппировкойМассив(Выражение, ВыраженияПолейГруппировки, ОтборЗаписей, ОтборГруппировок)
Разберем по шагам, как составить формулу для нашего примера:
"Максимум(Количество)"."Характеристика".Для того чтобы получить сумму максимумов характеристик на уровне «Производитель», мы оборачиваем массив в функцию Сумма. Итоговое выражение для ресурса на верхнем уровне будет выглядеть следующим образом:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Количество)", "Характеристика"))
Для корректного расчета итогов СКД должна точно знать, на каком уровне какую формулу применять. Выясним, как правильно распределить вычисления по группировкам на вкладке Ресурсы:
Количество) в таблицу ресурсов дважды.Максимум(Количество).Характеристика.
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Количество)", "Характеристика"))
Производитель и обязательно Общие итоги.Null.Иногда логика вычислений на верхнем уровне оказывается сложнее, чем простое суммирование. Например, если нам требуется отобрать только уникальные значения, отсортировать их или выполнить специфическую агрегацию. Для таких случаев применяется функция ВычислитьВыражениеСГруппировкойТаблицаЗначений.
Она работает аналогично версии с массивом, но возвращает полноценную структуру таблицы значений (ТЗ), к которой можно применять специализированные функции СКД. Рассмотрим пример, когда нам нужно на уровне «Производитель» вывести список всех уникальных характеристик, для которых значение ресурса превысило определенный порог, перечислив их через запятую:
СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("Характеристика", "Характеристика", "Максимум(Количество) > 10"), ", ")
Использование таблиц значений внутри выражений ресурсов СКД предоставляет неограниченные возможности для построения сложных аналитических отчетов без изменения структуры метаданных конфигурации.
Необходимо понимать внутренние механизмы работы СКД при использовании функций семейства ВычислитьВыражение. Проанализируем критически важные нюансы:
ВычислитьВыражениеСГруппировкойМассив происходят в оперативной памяти на стороне сервера приложений «1С:Предприятие» после того, как СУБД вернула плоскую выборку данных. Если отчет строится по сотням тысяч или миллионам детальных записей, это приведет к значительному потреблению RAM и снижению скорости формирования отчета.Если вы столкнулись с падением производительности при формировании отчета, наиболее правильным архитектурным решением будет перенос логики агрегации непосредственно в текст запроса схемы компоновки данных.
Выполним это по следующему алгоритму:
ВЫБРАТЬ
Продажи.Производитель КАК Производитель,
Продажи.Характеристика КАК Характеристика,
МАКСИМУМ(Продажи.Количество) КАК МаксимальноеКоличество
ПОМЕСТИТЬ ВТ_МаксимумыХарактеристик
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГРУППИРОВАТЬ ПО
Продажи.Производитель,
Продажи.Характеристика
;
ВЫБРАТЬ
ВТ.Производитель КАК Производитель,
СУММА(ВТ.МаксимальноеКоличество) КАК ИтоговыйПоказатель
ИЗ
ВТ_МаксимумыХарактеристик КАК ВТ
ГРУППИРОВАТЬ ПО
ВТ.Производитель
При таком подходе СУБД (например, MS SQL Server или PostgreSQL) выполнит группировку и агрегацию на своей стороне в разы быстрее, задействовав индексы, а СКД получит уже готовые сжатые данные для вывода в отчет без необходимости производить сложные манипуляции с массивами в оперативной памяти.