Как правильно рассчитать средние итоги в иерархической группировке СКД?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При построении отчетов в системе компоновки данных (СКД) часто возникает ситуация, когда стандартный механизм расчета ресурсов работает не так, как ожидает бизнес. Типичный пример — необходимость посчитать среднюю цену на уровнях иерархии номенклатуры при наличии подчиненных детальных записей (например, серий или характеристик).

Рассмотрим конкретную проблему: в отчете присутствует группировка по иерархии номенклатуры и подчиненная группировка по сериям. По каждой серии задана цена. Стандартная функция Среднее(Цена) на верхнем уровне иерархии (в папках) рассчитывает среднее арифметическое по всем детальным записям (сериям), входящим в эту папку. Однако бизнесу требуется другой показатель — среднее значение цены элементов номенклатуры, входящих в группу, без искажения за счет неравномерного количества серий у разных товаров.

Выясним причину проблемы

По умолчанию платформа 1С при выполнении агрегатных функций (таких как Среднее, Сумма, Количество) для иерархических узлов рассчитывает результат напрямую из исходных детальных записей набора данных. Если у одного элемента номенклатуры 2 серии, а у другого — 3 серии, то агрегация на уровне папки посчитает среднее по всем 5 сериям. Из-за этого конечный результат группировки первого и второго уровней иерархии получается некорректным с точки зрения расчета среднего по позициям номенклатуры.

Решение 1. Разделение группировок и использование языковых функций СКД

Разберем рабочий алгоритм решения этой задачи, который позволяет обойти ограничение стандартного расчета иерархии путем явного указания уровня агрегации данных.

Шаг 1. Корректировка запроса и полей набора данных

В тексте запроса набора данных добавим явное поле родителя для справочника номенклатуры. Это необходимо для явного построения уровней иерархии в структуре отчета:


ВЫБРАТЬ
    НоменклатураСсылка КАК Номенклатура,
    НоменклатураСсылка.Родитель КАК НоменклатураРодитель,
    Серия,
    Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры

На вкладке «Набор данных» в свойствах поля Номенклатура необходимо указать значение в колонке «Родитель» — НоменклатураРодитель.

Шаг 2. Настройка структуры отчета

В настройках структуры отчета сформируем следующую вложенность группировок вместо стандартной авто-иерархии:

  1. Группировка НоменклатураРодитель (Тип группировки: Иерархия)
  2. Вложенная группировка Номенклатура (Тип группировки: Элементы)
  3. Вложенная группировка Серия (Тип группировки: Элементы)

Шаг 3. Настройка формул расчета ресурсов

Перейдем на вкладку «Ресурсы» и зададим индивидуальные правила вычисления ресурса Цена для разных уровней группировки:

  1. Для детального уровня элементов номенклатуры добавляем первую строку ресурса:
    • Выражение: Среднее(Цена)
    • Рассчитывать по...: Номенклатура
  2. Для родительских групп и итоговых сумм добавляем вторую строку ресурса с применением специальной функции СКД:
    • Выражение: Среднее(ВычислитьВыражениеСГруппировкойМассив("Среднее(Цена)", "Номенклатура"))
    • Рассчитывать по...: НоменклатураРодитель Иерархия, Общий итог

Функция ВычислитьВыражениеСГруппировкойМассив сначала собирает массив средних цен для каждой номенклатуры внутри группы, а внешняя функция Среднее вычисляет среднее арифметическое уже из полученных значений номенклатур, игнорируя количество серий.

Решение 2. Использование настройки «Рассчитывать по...» с указанием иерархии

Если нет необходимости менять структуру запроса, вычисление средних итогов можно настроить напрямую в таблице ресурсов, разделив выражения для конечного элемента и иерархической папки.

Проанализируем параметры настройки ресурсов:

  1. Добавляем строку ресурса для элементов:
    Выражение: Среднее(Цена)
    Рассчитывать по: Номенклатура
  2. Добавляем отдельную строку для папок иерархии:
    Выражение: Среднее(ВычислитьВыражениеСГруппировкойМассив("Среднее(Цена)", "Номенклатура"))
    Рассчитывать по: Номенклатура Иерархия
  3. Добавляем строку для общего итога отчета:
    Выражение: Среднее(ВычислитьВыражениеСГруппировкойМассив("Среднее(Цена)", "Номенклатура"))
    Рассчитывать по: Общий итог

Решение 3. Использование связи двух наборов данных

В сложных отчетах правильный расчет иерархических средних показателей реализуется разделением данных на два набора:

  1. Объектный набор данных (Номенклатура): содержит список товаров и предварительно посчитанные средние цены по каждой номенклатуре.
  2. Детальный набор данных (Серии): содержит записи о сериях и их ценах.

На вкладке «Связи наборов данных» настраивается связь между объектами. В этом случае СКД организует дерево группировок корректно: агрегация цены по номенклатуре выполняется в первом наборе, а папочные итоги рассчитываются строго на базе средних цен элементов первого набора данных.

← На главную