Как в СКД рассчитать средний остаток по дням и просуммировать его в вышестоящих группировках и общем итоге?

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

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

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

В чем заключается проблема расчета итогов

Рассмотрим структуру отчета со следующей иерархией группировок:

  1. Ответственный
  2. Организация
  3. Номенклатура
  4. Характеристика
  5. День

Если для ресурса КоличествоКонечныйОстаток задать стандартное агрегатное выражение Среднее(КоличествоКонечныйОстаток), то на уровне группировки Характеристика СКД рассчитает среднее значение по дням. Однако на уровнях Номенклатура, Организация и в общем итоге система также продолжит вычислять среднее значение по всем строкам выборки, вместо того чтобы сложить полученные средние остатки по характеристикам.

Если же попытаться использовать функцию работы с массивами вида:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Среднее(КоличествоКонечныйОстаток)", "ХарактеристикаНоменклатуры"))

то на промежуточных уровнях результат может сойтись, но в строке Общий итог данные будут рассчитаны некорректно. Проанализируем причину такого поведения.

Причина ошибки в общем итоге

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

Когда во втором параметре передается только одно поле "ХарактеристикаНоменклатуры", система строит массив без учета уникальности всей вышестоящей иерархической цепочки. Если одна и та же характеристика или номенклатура встречается в разных организациях или у разных ответственных, в контексте общего итога происходит неверное агрегирование и схлопывание данных.

Для корректного суммирования на верхних уровнях и в общем итоге необходимо явно передавать весь перечень вышестоящих группировок, однозначно определяющих контекст строки.

Пошаговая настройка ресурсов СКД

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

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

Сохранение детальности выборки: роль поля «Обязательное»

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

Выясним причину: СКД автоматически оптимизирует SQL-запрос к базе данных. Если поле День не выводится в отчет, не используется в текущих группировках и отборах, платформа исключает его из секции ВЫБРАТЬ и СГРУППИРОВАТЬ ПО результирующего запроса. Данные схлопываются еще на уровне СУБД, и среднее по дням рассчитать становится невозможно.

Чтобы зафиксировать детализацию данных независимо от пользовательских настроек структуры отчета, выполним следующие действия:

  1. Откроем вкладку Наборы данных.
  2. В таблице полей набора найдем поле День (или поле периода, по которому считается среднее).
  3. В колонке Роль откроем свойства поля и установим флаг Обязательное.

Установка признака Обязательное гарантирует, что поле периода всегда будет присутствовать в тексте исполняемого запроса и группировке на уровне СУБД, сохраняя необходимую плотность строк для вычисления среднего остатка.

Альтернативные варианты оптимизации

Если отчет строится на больших объемах данных, постоянный расчет массива значений в памяти СКД может влиять на скорость формирования. Рассмотрим альтернативные архитектурные решения:

  1. Расчет среднего остатка на уровне запроса: можно заранее сгруппировать остатки по дням во временной таблице и вычислить среднее значение для комбинации Организация + Номенклатура + Характеристика средствами языка запросов. В этом случае в СКД передается уже готовый средний показатель, а на вкладке ресурсов используется стандартная и быстрая функция Сумма(КоличествоКонечныйОстаток).
  2. Использование механизма дополнения периодов: вместо ручных соединений с производственным календарем в запросе можно использовать виртуальную таблицу ОстаткиИОбороты с периодичностью День и настроить дополнение периодов в СКД (свойство поля Тип дополнения: День).
← На главную