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