При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда собираемые показатели имеют разный уровень аналитики. Например, продажи рассчитываются с детализацией до конкретного товара, а задолженность фиксируется только на уровне контрагента и договора. Если объединить эти данные в одном запросе с помощью левого соединения, сумма задолженности начнет дублироваться для каждой строки с товаром, искажая общие итоги.
Рассмотри подробно, как правильно настроить схему компоновки данных, чтобы показатель долга выводился только на уровне контрагента и договора, не дублируясь в детальных записях по номенклатуре.
Проанализируем ситуацию: при соединении таблицы остатков долга (по договорам) с таблицей продаж (по товарам) на одну строку договора может приходить несколько строк с товарами. В результате СУБД возвращает повторение одной и той же суммы долга в каждой детальной строке. Если использовать стандартное выражение ресурса Сумма(Долг), платформа сложит все повторяющиеся значения, что приведет к неверным итоговым суммам.
Самый простой и стандартный инструмент СКД — гибкая настройка вкладки Ресурсы. Разберем по шагам, как ограничить расчет ресурса для нижних уровней группировок:
Долг укажем выражение расчета, например: Сумма(Долг) или Максимум(Долг).Контрагент и Договор).Товар данный ресурс рассчитываться не будет, и значение на уровне детальных записей останется пустым.Если требуется корректно суммировать показатели по договорам на верхних уровнях без учета дублей в детальных строках, в выражении ресурса применяют специальные функции языка выражений СКД:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Долг)", "Договор"))
Данная формула сначала вычисляет максимальный долг по каждому договору, а затем суммирует полученные значения для контрагента или общего итога.
Еще один подход заключается в правильной подготовке структуры запроса без применения соединения таблиц. Выполним объединение двух таблиц (продаж и задолженности) через ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.Договор КАК Договор,
Продажи.Номенклатура КАК Товар,
0 КАК Долг,
Продажи.СуммаОборот КАК Продано
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Взаиморасчеты.Контрагент,
Взаиморасчеты.Договор,
NULL,
Взаиморасчеты.СуммаОстаток,
0
ИЗ
РегистрНакопления.Взаиморасчеты.Остатки(&Период, ) КАК Взаиморасчеты
При таком подходе данные по задолженности попадают в отдельную строку, где номенклатура равна NULL. В отчете СКД показатель Долг будет корректно суммироваться на уровне договора и контрагента, не накладываясь на строки с товарами.
Посмотрим на наиболее универсальный архитектурный вариант в СКД — разделение данных по разным наборам:
Контрагент, Договор, Товар, Продано.Контрагент, Договор, Долг.Контрагент и Договор.При такой схеме СКД самостоятельно свяжет данные в памяти. Поле Долг будет относиться только к уровню договора и контрагента и не будет детализироваться до строк с номенклатурой.
Если данные уже загружены в один набор, можно убрать вывод поля Долг из детальной группировки на этапе настройки структуры отчета:
Товар перейдем на вкладку Выбранные поля и снимем флаг Авто.Товар только поля Товар и Продано.Долг добавим в выбранные поля для родительских группировок Контрагент и Договор.Таким образом, ячейка долга на уровне детальных записей товаров останется пустой, а на уровне договоров выведутся точные суммарные показатели.