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

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда данные из шапки документа (например, СуммаДоставки) объединяются с данными табличной части (список товаров). В результате в выборке запроса сумма доставки повторяется в каждой строке с товаром. Если просто применить ресурс СУММА(СуммаДоставки), итоговое значение в группировках по дате или по отчету в целом будет неверным, так как оно суммирует доставку столько раз, сколько товаров в документе.

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

Причина возникновения проблемы

Рассмотрим структуру стандартного запроса, который вызывает подобные сложности:


ВЫБРАТЬ
    Ссылка,
    Дата,
    Товар,
    СуммаДоставкиДокумента
ИЗ
    Документ.РеализацияТоваровУслуг.Товары

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

Способ 1. Использование функции ВычислитьВыражениеСГруппировкойМассив

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

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

СУММА(ВычислитьВыражениеСГруппировкойМассив("МАКСИМУМ(СуммаДоставкиДок)", "Ссылка"))

Разберем по шагам, как работает эта формула:

  1. МАКСИМУМ(СуммаДоставкиДок): Внутри каждого конкретного документа (группировка Ссылка) мы берем максимальное значение суммы. Так как сумма во всех строках одного документа одинакова, максимум вернет нам ровно одно значение (500 из нашего примера).
  2. ВычислитьВыражениеСГруппировкойМассив(..., "Ссылка"): Эта функция обходит все документы в текущем контексте (например, за день) и составляет из полученных «максимумов» массив значений. Если за день было три документа, массив будет выглядеть так: [500, 300, 1000].
  3. СУММА(...): Внешняя функция складывает элементы этого массива, получая корректный итог (1800), игнорируя количество строк внутри самих документов.

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

Способ 2. Объединение (UNION) в тексте запроса

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

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


ВЫБРАТЬ
    Ссылка КАК Ссылка,
    Товар КАК Товар,
    0 КАК СуммаДоставки
ИЗ
    Документ.РеализацияТоваровУслуг.Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Ссылка,
    NULL,
    СуммаДоставки
ИЗ
    Документ.РеализацияТоваровУслуг

В этом случае товары и суммы доставки разнесены по разным строкам. Чтобы отчет выглядел презентабельно, выполним следующие настройки в СКД:

  1. Для поля Товар в настройках набора данных установим флаг Игнорировать значения NULL. Это позволит избежать появления пустых строк в группировках по товарам.
  2. В качестве ресурса для поля СуммаДоставки теперь можно использовать обычную функцию СУММА(СуммаДоставки), так как каждое значение встречается в выборке ровно один раз.

Способ 3. Расширенная настройка расчета ресурсов

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

В колонке «Рассчитывать по...» нужно четко отметить, к каким уровням относится каждая формула. Это гарантирует, что на уровне документа пользователь увидит корректную цифру, а на уровне итогов — правильную сумму этих цифр.

Анализ сложных выражений (на примере БСП)

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

Рассмотрим пример сложной формулы:

СУММА(ВычислитьВыражениеСГруппировкойМассив("(ВычислитьВыражение(""СУММА(ЗамерыСумма)/СУММА(КоличествоЗамеров)"",,,""Первая"", ""Последняя"") ... )"))

Важные параметры здесь:

Для повседневных задач учета (доставка, масса нетто, услуги в документах) достаточно базового понимания ВычислитьВыражениеСГруппировкойМассив. Это избавляет от необходимости писать громоздкие вложенные запросы и существенно упрощает поддержку отчета.

Рекомендации по выбору метода

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

  1. Если отчет небольшой и важна скорость разработки — используйте Способ 1 (функция в ресурсах). Это «золотой стандарт» современной разработки на 1С.
  2. Если вы работаете с огромными массивами данных (миллионы строк) и отчет «тормозит» при компоновке — лучше применить Способ 2 (UNION в запросе), чтобы перенести нагрузку на SQL-сервер.
  3. Если вам нужно видеть сумму доставки только в итогах, а в строках товаров она мешает — просто не добавляйте её в детальные записи, оставив расчет только для группировок верхнего уровня.

Применяя эти техники, вы сможете создавать точные и производительные отчеты, которые корректно обрабатывают любые иерархические связи данных в системе 1С:Предприятие.

← На главную