При разработке сложных аналитических отчетов в системе компоновки данных (СКД), таких как ABC-анализ или отчеты по долям продаж, программисты часто сталкиваются с необходимостью расчета нарастающего итога. Особую сложность вызывает ситуация, когда итог нужно посчитать не по простому полю, а по ресурсу, который сам является расчетным (например, процентная доля). В процессе решения этой задачи система часто выдает ошибку: «Использование вложенных агрегатных функций не допускается».
В этой статье мы подробно разберем, почему возникает эта ошибка, как правильно использовать механизмы СКД для вычисления накопительных сумм и рассмотрим пошаговые алгоритмы настройки ресурсов.
Типичная ситуация: у нас есть ресурс ДоляПродаж, который рассчитывается как Сумма(Продажи) / ВычислитьВыражение("Сумма(Продажи)", "ОбщийИтог") * 100. Когда мы пытаемся рассчитать нарастающий итог по этому ресурсу, используя конструкцию Сумма(ДоляПродаж) внутри функции ВычислитьВыражение, СКД видит это как попытку применить агрегатную функцию (Сумма) к результату другой агрегатной функции (уже существующей внутри ДоляПродаж). В терминах 1С это и есть недопустимое вложение.
Для решения задачи нам необходимо изменить подход к построению выражений, перенеся часть логики на уровень вычисляемых полей или используя возможности функции ВычислитьВыражение с явным указанием контекста группировок.
Функция ВычислитьВыражение является основным инструментом для работы с нарастающими итогами. Рассмотрим ее синтаксис для нашей задачи:
ВычислитьВыражение("Сумма(ИмяПоля)", , , "Первая", "Текущая")
Разберем параметры подробнее:
Сумма(СуммаОборот))."Первая" указывает системе начинать суммирование с самой первой строки в текущем контексте (например, с первой строки магазина)."Текущая" указывает, что суммировать нужно до текущей строки включительно.Проанализируем ситуацию, когда нам нужно получить накопительный процент продаж по номенклатуре внутри группы. Самый эффективный и безошибочный способ — не пытаться суммировать саму «долю», а суммировать выручку нарастающим итогом и делить ее на общую выручку группы. Математически это даст тот же результат, но позволит избежать вложенных агрегатов.
Рассмотрим выражение для ресурса НакопительныйИтогДоли:
ВычислитьВыражение("Сумма(СуммаВыручки)", , , "Первая", "Текущая")
/
ВычислитьВыражение("Сумма(СуммаВыручки)", "ИмяГруппировкиРодителя")
* 100
В данном примере:
Если математическое выражение получается слишком громоздким, мы можем использовать вкладку «Вычисляемые поля». Выясним, в чем преимущество: поля, определенные здесь, считаются до того, как данные попадают в механизм расчета ресурсов. Это позволяет нам подготовить данные.
Например, создадим вычисляемое поле БазоваяДоля. Но важно помнить: если в выражении вычисляемого поля нет агрегатных функций (Сумма, Максимум), то в ресурсах мы сможем использовать их без ошибок. Если же нам нужно оперировать уже агрегированными данными, лучше придерживаться метода из Шага 2.
Иногда возникают задачи, где нарастающий итог нужно посчитать по средним значениям или другим сложным показателям. В этом случае на помощь приходит функция ВычислитьВыражениеСГруппировкойМассив. Она позволяет сначала рассчитать значения для каждой строки группировки, собрать их в массив, а затем применить к этому массиву функцию Сумма.
Рассмотрим пример логики:
Сумма(ВычислитьВыражениеСГруппировкойМассив(
"Среднее(Цена)",
"Номенклатура",
,
"НомерСтроки <= " + НомерСтроки
))
Хотя этот метод более ресурсоемкий, он позволяет обходить практически любые ограничения на вложенность функций, так как фактически создает промежуточную таблицу значений в памяти.
Проанализируем несколько критических моментов, которые могут повлиять на корректность отчета:
ВычислитьВыражение с параметрами "Первая" и "Текущая" пересчитает итоги в новом порядке. Это идеально подходит для рейтинга продаж (Топ-менеджмент), где важна последовательность от большего к меньшему."Поле не обнаружено", так как ресурсы рассчитываются параллельно или в порядке, не гарантирующем наличие значения. Всегда используйте полные формулы через исходные поля набора данных.ГруппировкаМагазин, убедитесь, что в формуле написано "ГруппировкаМагазин" (в кавычках).Подведем итог: для успешного расчета нарастающего итога в СКД следует избегать вложенности агрегатных функций путем дублирования логики расчета в одном выражении и активного использования возможностей функции ВычислитьВыражение с указанием границ "Первая" и "Текущая". Это обеспечит стабильную работу отчета и корректность данных при любых настройках группировок пользователем.