При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются со стандартным поведением агрегатных функций. По умолчанию, если мы устанавливаем ресурс как Среднее(Поле), система рассчитывает среднее значение по всем детальным записям, входящим в итог. Однако в бизнес-логике часто встречается иная задача: необходимо сначала вычислить среднее значение внутри каждой группы (например, за месяц или по конкретному подразделению), а в общих итогах — просуммировать эти полученные средние показатели.
Рассмотрим подробнее, как реализовать этот механизм, разберем по шагам работу с функциями языка выражений СКД и выясним причины, по которым стандартные настройки «мышкой» в данном случае не подходят.
Прежде чем перейти к решению, проанализируем ситуацию с математической точки зрения. Если система просто рассчитывает среднее значение для общего итога, она берет сумму всех записей и делит на их количество. Если же мы хотим получить сумму средних, нам нужно заставить СКД выполнить двухэтапный расчет. Стандартная вкладка «Ресурсы» не позволяет выбрать тип агрегации «Сумма от Среднего» простым выбором из выпадающего списка. Именно поэтому нам придется использовать выражения СКД.
Основным и наиболее эффективным инструментом для решения подобных задач является функция ВычислитьВыражениеСГруппировкойМассив. Эта функция позволяет нам собрать результаты расчетов по определенной группировке в массив, который затем может быть обработан другой агрегатной функцией.
Рассмотрим пример выражения, которое необходимо прописать в поле «Выражение» на закладке «Ресурсы»:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Среднее(Ресурс)", "ИмяГруппировкиКолонки"))
Разберем, что именно происходит в этом выражении:
Среднее(Ресурс) вычисляет среднее значение для каждой отдельной группировки.ВычислитьВыражениеСГруппировкойМассив обходит все элементы указанной группировки (например, колонки с месяцами) и помещает среднее значение каждого месяца в массив.Сумма(...) складывает все элементы этого массива, формируя итоговое значение.Для того чтобы функция ВычислитьВыражениеСГруппировкойМассив отработала корректно, нам необходимо убедиться, что у группировки в настройках отчета задано Имя. По умолчанию 1С не присваивает имен автоматическим группировкам.
Выполним следующие действия:
КолонкаПериод."КолонкаПериод" мы должны использовать во втором параметре нашей функции.Просто прописать формулу в ресурсах недостаточно. Выясним причину, по которой итоги могут отображаться некорректно: это неверно заданная область расчета. На вкладке «Ресурсы» в колонке «Рассчитывать по...» необходимо четко ограничить, где именно применяется наше суммирование средних.
Как правило, для детальных записей и самих группировок должно рассчитываться обычное Среднее(Поле), а вот для вышестоящих группировок и Общих итогов — наша сложная формула. В списке «Рассчитывать по» следует отметить только те уровни иерархии, где требуется сложение результатов.
Пример настройки ресурсов:
// Для группировки по подразделению (обычное среднее):
Среднее(Продажи)
// Для общих итогов (сумма средних по месяцам):
Сумма(ВычислитьВыражениеСГруппировкойМассив("Среднее(Продажи)", "Месяц"))
Проанализируем ситуацию, когда в некоторых периодах данные отсутствуют. Если Среднее(Поле) вернет NULL, функция Сумма по массиву проигнорирует это значение. Однако, если бизнес-логика требует, чтобы отсутствие данных считалось как ноль, следует модифицировать внутреннюю функцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("ЕстьNull(Среднее(Ресурс), 0)", "ИмяГруппировки"))
Это обеспечит корректность математических операций и исключит неопределенность в итоговых ячейках отчета.
Рассмотрим важный аспект работы с большими отчетами. Использование ВычислитьВыражениеСГруппировкойМассив заставляет систему выполнять дополнительные проходы по данным и выделять память под временные массивы. Если ваш отчет содержит десятки тысяч колонок или строк, это может привести к замедлению работы.
В таких случаях мы рекомендуем предварительно рассчитывать средние значения в самом Запросе на уровне временных таблиц, чтобы СКД получала уже подготовленные агрегаты. Тогда в компоновке останется лишь применить простую функцию Сумма().
ГруппаКолонок).Сумма(ВычислитьВыражениеСГруппировкойМассив("Среднее(ИмяПоля)", "ГруппаКолонок")).Таким образом, мы видим, что СКД предоставляет мощный функционал для реализации практически любых алгоритмов расчета итогов, выходящих за рамки стандартного агрегирования. Правильное использование функций вычисления выражений по группировкам позволяет создавать сложные аналитические отчеты без написания кода на языке 1С, исключительно средствами декларативной настройки схемы.