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

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

В процессе разработки отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с классической проблемой: «задвоением» (или дублированием) ресурсов при связи таблиц типа «один-ко-многим». Типичный пример — связь шапки или табличной части родительского документа (например, «Задание на отгрузку») с табличной частью подчиненного документа (например, «Расходная накладная» или «Реализация товаров и услуг»).

Когда к одной строке родительского документа привязывается несколько строк из подчиненных таблиц, данные родителя дублируются в итоговой выборке. В результате стандартное суммирование через ресурс СУММА выдает некорректный, завышенный общий итог. Выясним причину этой проблемы и подробно разберем четыре профессиональных способа её решения.

Анализ проблемы на практическом примере

Рассмотрим ситуацию, описанную пользователем на форуме. У нас есть документ «Задание на отгрузку №1» с общим весом 250 кг. К нему привязаны три расходных документа, которые частично распределяют этот вес:

Обратите внимание: Расходная №2 и Расходная №3 ссылаются на одну и ту же строку «Задания на отгрузку» с весом 150. При обычном левом соединении таблиц в запросе СКД строка с весом 150 продублируется. Если мы просто просуммируем колонку «Вес», то получим: 100 + 150 + 150 = 400. Однако реальный суммарный вес по заданию на отгрузку должен быть равен 250 (100 + 150).

Ниже представлены четыре метода, которые позволят нам рассчитать итоги корректно.

Способ 1. Связи наборов данных (рекомендуемый архитектурный подход)

Вместо того чтобы объединять таблицы левым соединением внутри одного SQL-запроса, разработчики платформы 1С рекомендуют разделять данные на два независимых набора данных и связывать их на уровне самой СКД. Это наиболее надежный и «родной» механизм системы компоновки.

Рассмотрим этот процесс по шагам:

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

Почему это решает проблему задвоения? При использовании связей наборов данных СКД рассчитывает итоги по каждому набору абсолютно независимо. Вес задания на отгрузку будет просуммирован строго по первому набору (где нет дублей строк), а детальные данные по расходным накладным корректно «пристыкуются» к отчету без искажения итоговых сумм.

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

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

Для реализации этого метода выполним следующие настройки:

  1. Перейдем на вкладку «Ресурсы» в СКД.
  2. В строке поля Вес в колонке «Выражение» пропишем формулу:

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

Проанализируем, как работает эта формула:

Важная тонкость: Если в вашем отчете присутствуют другие вышестоящие группировки (например, Организация -> Склад -> ЗаданиеНаПеревозку), во втором параметре функции (выражение полей группировки) необходимо перечислить их через запятую в кавычках. Это позволит СКД правильно собирать массив уникальных значений на каждом уровне иерархии:


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

Способ 3. Предварительное агрегирование (сворачивание) в запросе

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

Посмотрим на пример построения такого запроса:


ВЫБРАТЬ
    Реализация.Ссылка КАК Реализация,
    Реализация.Сделка КАК ЗаданиеНаОтгрузку,
    СУММА(Реализация.Вес) КАК ВесВРеализации
ПОМЕСТИТЬ ВТ_Реализации
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
СГРУППИРОВАТЬ ПО
    Реализация.Ссылка,
    Реализация.Сделка;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Задание.Ссылка КАК ЗаданиеНаОтгрузку,
    Задание.Вес КАК ВесЗадания,
    ЕСТЬNULL(ВТ_Реализации.ВесВРеализации, 0) КАК ВесВРеализации
ИЗ
    Документ.ЗаданиеНаОтгрузку КАК Задание
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Реализации КАК ВТ_Реализации
    ПО ВТ_Реализации.ЗаданиеНаОтгрузку = Задание.Ссылка

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

Минус метода: он применим только в том случае, если в финальном отчете не требуется выводить детальные строки по каждой отдельной расходной накладной (так как во временной таблице мы их уже свернули).

Способ 4. Настройка расчета ресурсов по отдельным группировкам

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

Настроим расчет ресурса следующим образом:

  1. Добавим поле Вес в таблицу ресурсов первый раз. В выражении укажем Максимум(Вес), а в колонке «Рассчитывать по...» выберем группировку ЗаданиеНаПеревозку. Это гарантирует, что на уровне самого документа вес не задвоится.
  2. Добавим поле Вес в таблицу ресурсов второй раз. В поле «Выражение» пропишем формулу с ВычислитьВыражениеСГруппировкойМассив, а в колонке «Рассчитывать по...» укажем «Общий итог» и другие вышестоящие группировки.
  3. Для детальных записей (строк расходных накладных) вывод веса задания на отгрузку можно отключить вообще или выводить 0, чтобы не путать пользователя повторяющимися цифрами.

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

← На главную