При разработке отчетов на Системе Компоновки Данных (СКД) программисты часто сталкиваются с классической проблемой: когда в одном наборе данных соединяются «шапка» документа и его «табличная часть», числовые показатели из шапки начинают дублироваться в каждой строке товаров. Это приводит к тому, что общие итоги по клиенту или организации становятся завышенными ровно в столько раз, сколько строк товаров содержится в документе. В этой статье мы подробно разберем, как правильно настроить расчет ресурсов, чтобы на нижних уровнях отображались нули или пустые значения, а на верхних — корректные суммы.
Рассмотрим стандартную ситуацию. У нас есть трехуровневая группировка: Клиент —> Накладная —> Товар. Ресурс Оплата является реквизитом документа (шапки). В запросе мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ документа с его табличной частью Товары. Проанализируем, что происходит на уровне данных: если в одной накладной на сумму 10 000 рублей содержится 5 разных товаров, то после соединения в выборке окажется 5 строк, и в каждой из них в поле Оплата будет стоять 10 000. При обычном суммировании СКД выдаст итог 50 000 вместо положенных 10 000.
Многие пытаются решить проблему простым отключением отображения поля в выбранных полях группировки. Однако, как показывает практика, это не помогает: даже если поле не выводится на экран, СКД продолжает использовать его значения для расчета итогов вышестоящих уровней.
Этот метод является наиболее гибким, так как позволяет решить задачу в рамках одного набора данных (одного запроса). Основная идея заключается в том, чтобы сказать СКД: «Сначала выбери уникальные значения для каждой накладной, а затем сложи их».
Разберем по шагам настройку на вкладке Ресурсы в конструкторе СКД:
Оплата в список ресурсов несколько раз (для разных уровней группировки).Товар) в колонке «Выражение» укажем просто 0. В колонке «Рассчитывать по...» отметим только группировку Товар. Это уберет «мусорные» значения из детальных строк.Накладная укажем выражение Максимум(Оплата). Поскольку в рамках одной накладной сумма оплаты везде одинакова, функция Максимум (или Минимум) вернет верное значение шапки.Клиент и Общий итог) необходимо использовать специальную конструкцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Оплата)", "Накладная"))
Проанализируем, как работает эта функция:
"Максимум(Оплата)" — выражение, которое вычисляется для каждой группы."Накладная" — имя группировки, в разрезе которой нужно собрать значения в массив.ВычислитьВыражениеСГруппировкойМассив — собирает массив из уникальных оплат по каждой накладной.Сумма(...) — складывает полученные элементы массива.Важное замечание: Чтобы это сработало, рекомендуется явно задать имена группировкам на вкладке «Настройки» (правой кнопкой по группировке — «Установить имя»), хотя в простых отчетах СКД может подтянуть имя поля группировки автоматически.
Если структура отчета позволяет, профессиональным подходом считается разделение данных на два независимых набора. Это полностью исключает дублирование на уровне SQL-запроса.
Рассмотрим алгоритм реализации:
Ссылка, Партнер, СуммаДокумента).Ссылка, Номенклатура, Количество).Ссылка (Источник — Набор 1, Приемник — Набор 2).В этом случае ресурс Оплата будет принадлежать только первому набору. Когда СКД начнет выводить итоги по клиенту, она возьмет данные из Набора 1, где на каждую накладную приходится строго одна запись. Суммы по товарам из Набора 2 никак не повлияют на математику расчета оплат.
Иногда возникают ситуации, когда использование массивов кажется избыточным. Можно попробовать использовать функцию ВычислитьВыражение с указанием области анализа. Рассмотрим пример выражения для ресурса:
ВычислитьВыражение("Сумма(Оплата)", "Накладная", , "Первая", "Первая")
Такой подход заставляет СКД брать сумму только первой записи в каждой группировке Накладная. Однако этот метод имеет существенный минус: если пользователь наложит отбор по конкретному товару, который не является первым в списке накладной, сумма может просто «исчезнуть» или рассчитаться неверно. Поэтому использование ВычислитьВыражениеСГруппировкойМассив остается более надежным вариантом.
Выясним причину, почему даже при правильных расчетах отчет может выглядеть неопрятно. Это часто связано с пустыми значениями (NULL). Если вы используете ЛЕВОЕ СОЕДИНЕНИЕ и для какой-то накладной нет движений по оплате, функции агрегации могут вести себя непредсказуемо.
Рекомендуем в поле выражения ресурса всегда добавлять проверку на NULL:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(ЕстьNull(Оплата, 0))", "Накладная"))
Также помните, что при использовании функции ВычислитьВыражениеСГруппировкойМассив нельзя вкладывать агрегатные функции друг в друга напрямую (например, Сумма(Максимум(...)) без использования контекста ВычислитьВыражение). Платформа выдаст ошибку «Использование вложенных агрегатных функций не допускается».
Подведем итог: для корректного исключения ресурсов из нижних группировок используйте либо связи наборов данных (самый чистый метод), либо сложные выражения ресурсов с использованием массивов группировок. Это гарантирует точность финансовых показателей в ваших отчетах.