При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда стандартные агрегатные функции (Сумма, Среднее) в ресурсах работают корректно для детальных записей, но выдают неверный результат в общих итогах. Особенно остро эта проблема стоит при расчете относительных показателей, таких как процент совместных продаж, наценка или доля рынка. Рассмотрим ситуацию, когда по строкам нам нужен расчет по сложной формуле, а в итогах — среднее арифметическое этих строк.
Разберем типичный пример: отчет по анализу совместных продаж групп товаров. Допустим, у нас есть формула, которая определяет процент совместных покупок. Если товаров из второй группы куплено больше, чем из первой, мы считаем это как 100%, в противном случае — вычисляем долю. Проблема заключается в том, что СКД по умолчанию применяет ту же формулу ресурса к итоговой строке, подставляя в нее суммарные значения всех показателей. В результате в итоге мы снова получаем 100%, хотя по факту средний процент по всем контрагентам может быть значительно ниже.
Проанализируем исходную формулу, которую можно использовать в поле ресурса для детальных записей:
ВЫБОР
КОГДА Сумма(КоличествоСовместно) = 0 ИЛИ Сумма(Количество) = 0
ТОГДА 0
ИНАЧЕ ВЫБОР
КОГДА Сумма(КоличествоСовместно) > Сумма(Количество)
ТОГДА 100
ИНАЧЕ Сумма(КоличествоСовместно) / Сумма(Количество) * 100
КОНЕЦ
КОНЕЦ
Для каждой строки (например, по конкретному контрагенту) эта логика работает безупречно. Однако в строке "Итого" СКД сложит всё КоличествоСовместно и всё Количество по всем контрагентам. Если общие продажи совместных товаров велики, итог всегда будет показывать 100%, что не дает управленческой информации о том, каков же средний результат по базе клиентов.
Для того чтобы получить в итогах именно среднее значение из уже рассчитанных процентов по каждой строке, нам необходимо заставить СКД сначала вычислить проценты для каждого контрагента, собрать эти значения в массив и только потом применить к этому массиву функцию Среднее. Рассмотрим, как это реализовать по шагам.
Перейдем на вкладку Ресурсы в схеме компоновки данных и выполним следующие действия:
ПроцентСовместных).Выражение для расчета среднего по массиву будет выглядеть так:
Среднее(ВычислитьВыражениеСГруппировкойМассив("
ВЫБОР
КОГДА Сумма(КоличествоСовместно) = 0 ИЛИ Сумма(Количество) = 0
ТОГДА 0
ИНАЧЕ ВЫБОР
КОГДА Сумма(КоличествоСовместно) > Сумма(Количество)
ТОГДА 100
ИНАЧЕ Сумма(КоличествоСовместно) / Сумма(Количество) * 100
КОНЕЦ
КОНЕЦ", "Контрагент"))
Проанализируем, что происходит в этой формуле. Функция ВычислитьВыражениеСГруппировкойМассив принимает два основных параметра: строковое выражение (наша исходная формула расчета процента) и имя группировки, в разрезе которой нужно произвести расчет. СКД виртуально совершает обход всех контрагентов, вычисляет для каждого процент по формуле и складывает результаты в массив. Затем внешняя функция Среднее вычисляет среднее арифметическое элементов этого массива.
Часто в итогах мы видим числа с огромным количеством знаков после запятой. Чтобы привести результат к презентабельному виду, мы можем использовать функцию ВЫРАЗИТЬ прямо в выражении ресурса. Посмотрим, как модифицировать формулу для получения трех знаков после запятой:
Выразить(Среднее(ВычислитьВыражениеСГруппировкойМассив("
ВЫБОР
КОГДА Сумма(КоличествоСовместно) = 0 ИЛИ Сумма(Количество) = 0
ТОГДА 0
ИНАЧЕ ВЫБОР
КОГДА Сумма(КоличествоСовместно) > Сумма(Количество)
ТОГДА 100
ИНАЧЕ Сумма(КоличествоСовместно) / Сумма(Количество) * 100
КОНЕЦ
КОНЕЦ", "Контрагент")), "Число(10,3)")
Важный нюанс: при использовании ВЫРАЗИТЬ применяется правило банковского округления. Если вам требуется строгое математическое округление или просто эстетичный вид в отчете без изменения типа данных, лучше воспользоваться колонкой Оформление в настройках поля СКД, где в параметре "Формат" указать нужную точность (например, ЧЦ=10; ЧДЦ=2).
Рассмотрим несколько важных моментов, которые стоит учитывать при использовании данного метода:
ВычислитьВыражение...) более ресурсозатратно, чем простая сумма. Если в отчете выводятся десятки тысяч контрагентов, формирование итогов может занять заметное время, так как СКД требуется хранить промежуточные расчеты в памяти."Контрагент" в функции должен соответствовать реальному имени поля в наборе данных. Если вы измените структуру отчета и сгруппируете данные, например, по "Менеджеру", итоговое среднее всё равно будет считаться "по контрагентам", если вы не измените формулу.NULL. В таких случаях полезно оборачивать части выражения в функцию ЕСТЬNULL(..., 0), чтобы избежать ошибок вычисления среднего.Проанализируем ситуацию: всегда ли нам нужно именно среднее арифметическое? В бизнесе часто важнее взвешенное среднее. Если один мелкий клиент купил товар со 100% совпадением, а крупный оптовик — с 10%, то среднее арифметическое будет (100+10)/2 = 55%. Однако с точки зрения прибыли общий процент совместных продаж по компании может быть гораздо ближе к 10%.
Для расчета взвешенного среднего в итогах не нужно использовать массивы. Достаточно оставить стандартную формулу суммы:
Сумма(КоличествоСовместно) / Сумма(Количество) * 100
Выбор между этими двумя методами зависит исключительно от требований бизнес-заказчика к конкретному отчету. Если цель — увидеть "среднюю температуру по больнице" среди клиентов, используем метод с массивом. Если цель — общая эффективность продаж, используем простую агрегацию.
Таким образом, мы выяснили, что СКД предоставляет мощный инструментарий для гибкой настройки итогов. Использование функций ВычислитьВыражениеСГруппировкойМассив позволяет реализовывать практически любую логику агрегации данных, выходящую за рамки простых арифметических операций.