Почему двоятся суммы в группировке СКД при добавлении поля «Регистратор» и как это исправить?

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

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

Разберем основные причины, приводящие к некорректным итогам:

  1. Различная гранулярность данных при соединениях: если в запросе выполняется ЛЕВОЕ СОЕДИНЕНИЕ таблицы заказов (или остатков) с таблицей движений по регистраторам, то на одну запись заказа формируется несколько строк по документам-движениям. При стандартном суммировании Сумма(Поле) платформа складывает значение сальдо столько раз, сколько строк движений вернул запрос.
  2. Ошибки в настройке ролей полей-периодов: механизм расчета остатков в СКД требует строгой непрерывной иерархии периодов. Если в документе формируется несколько строк движений, отсутствие поля НомерСтроки с ролью младшего периода приводит к сбою расчета итогов.
  3. Отключение обязательности периодов: снятие флага «Обязательное» у родительского поля (например, ПериодСекунда) позволяет компоновщику макета исключить его из итогового текста SQL-запроса, из-за чего виртуальная таблица теряет срез данных во времени.

Способ 1. Использование встроенных функций СКД в выражении ресурса

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

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

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

В колонке «Рассчитывать по...» для этой строки выбираем вышестоящие уровни и «Общий итог». Для уровня самого заказа и регистратора указываем более простое выражение:

Максимум(Сальдо)

Альтернативный вариант агрегации, предложенный в обсуждении, использует встроенные типы коллекций СКД:

Сумма(Массив(ТаблицаЗначений(Различные Сальдо, Заказ)))

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

Способ 2. Разделение данных на независимые наборы

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

  1. Набор данных 1 (Запрос): выбирает основные разрезы и их суммовые показатели без документов движения (например, только Заказ и Сальдо).
  2. Набор данных 2 (Запрос): выбирает детальные движения, поле Регистратор и связующее поле Заказ.
  3. На вкладке «Связи наборов данных» связываем первый набор со вторым по полю Заказ.

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

Способ 3. Проверка ролей периодов и настроек виртуальной таблицы

Если отчет строится по виртуальным таблицам регистров накопления (например, ОстаткиИОбороты), проверим корректность настроек полей:

  1. Убедимся, что в выборку запроса включены поля ПериодСекунда, Регистратор и НомерСтроки.
  2. Проверим правильность назначения ролей на вкладке «Наборы данных»:
    
    НомерСтроки   -> Роль: Период, 1 (Дополнительный)
    Регистратор   -> Роль: Период, 2
    ПериодСекунда -> Роль: Период, 3
    
  3. Убедимся, что для поля ПериодСекунда установлен флаг «Обязательное», предотвращающий его оптимизацию компоновщиком при формировании макета.

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

← На главную