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