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