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