При разработке отчетов в Системе компоновки данных (СКД) разработчики часто сталкиваются с необходимостью вычисления относительных показателей, таких как процент возвратов, маржинальность или доля продаж. Попытка разделить один показатель на другой в вычисляемых полях нередко приводит к ошибке деления на ноль или выводу пустых значений в группировках отчета.
В этой статье мы подробно проанализируем причины возникновения этой проблемы и разберем проверенные способы её решения.
Разберем механику работы Системы компоновки данных. Когда мы добавляем выражение на вкладку Вычисляемые поля, платформа по умолчанию пытается выгрузить и рассчитать данную формулу для каждой детальной строки исходной таблицы данных. Если в конкретной детальной записи продажи отсутствовали (значение равен 0), то операция деления вызывает фатальную ошибку вычисления еще до того, как данные попадут в итоговые группировки.
Рассмотрим популярные заблуждения при решении этой задачи:
ЕСТЬNULL: Функция ЕСТЬNULL проверяет поле только на отсутствие значения (NULL). Числовой ноль 0 является действительным числовым значением, поэтому ЕСТЬNULL(СуммаПродаж, 0) не защищает от операции деления на ноль.ВЫБОР КОГДА СуммаПродаж > 0 ТОГДА ... на уровне вычисляемых полей проверяет значение в каждой отдельной строке. В группировках, где сумма продаж складывается из нескольких записей, такое построчное условие дает некорректный результат или пустое значение.СУММА(Процент) на вкладке ресурсов приводит к математической ошибке, так как проценты по группировкам нельзя просто складывать — их необходимо рассчитывать заново из итоговых сумм.Наиболее правильным и простым решением является перенос расчета процента на вкладку Ресурсы с использованием явных агрегатных функций СУММА внутри условия.
Рассмотрим пошагово порядок настройки:
ПроцентВозврата. Поле выражения можно оставить пустым или указать базовое наименование.ПроцентВозврата.
ВЫБОР
КОГДА СУММА(СуммаПродаж) > 0
ТОГДА СУММА(СуммаВозвратов) / СУММА(СуммаПродаж) * 100
ИНАЧЕ 0
КОНЕЦ
Такой подход гарантирует, что система сначала посчитает итоговую сумму продаж и итоговую сумму возвратов для текущего уровня группировки (например, по номенклатуре или контрагенту), а затем выполнит безопасное деление только при условии, что итоговые продажи больше нуля.
Если логика расчета процента сложная или используется в нескольких отчетах, вычисление можно вынести в серверный общий модуль конфигурации.
Рассмотрим пример экспортной функции в общем модуле:
Функция РассчитатьПроцентВозврата(Знач СуммаВозвратов, Знач СуммаПродаж) Экспорт
Если Не ЗначениеЗаполнено(СуммаПродаж) Или СуммаПродаж = 0 Тогда
Возврат 0;
КонецЕсли;
Возврат Округление(СуммаВозвратов / СуммаПродаж * 100, 2);
КонецФункции
На вкладке Ресурсы в поле выражения вызываем созданную функцию, передавая в нее агрегированные суммы:
ИмяВашегоОбщегоМодуля.РассчитатьПроцентВозврата(СУММА(СуммаВозвратов), СУММА(СуммаПродаж))
Если структура отчета фиксирована, расчет показателей можно вынести непосредственно в текст запроса. Чтобы избежать ошибок при формировании итогов, расчет производят во временных таблицах или вложенных запросах после выполнения группировки СГРУППИРОВАТЬ ПО.
Проанализируем пример фрагмента запроса:
ВЫБОР
КОГДА ВложенныйЗапрос.СуммаПродаж > 0
ТОГДА ВложенныйЗапрос.СуммаВозвратов / ВложенныйЗапрос.СуммаПродаж * 100
ИНАЧЕ 0
КОНЕЦ КАК ПроцентВозврата
При таком подходе в СКД передаются уже рассчитанные значения, однако важно помнить: на уровне итоговых группировок компоновки данных данный процент все равно потребует пересчета через ресурс, так как суммировать проценты нельзя.
Проанализируем ключевые ограничения платформы 1С при работе с выражениями СКД:
Деление на ноль в СКД всегда прерывает вычисление выражения, в отличие от некоторых СУБД, возвращающих NULL. Поэтому проверка знаменателя обязательна.
В выражениях вычисляемых полей нельзя использовать имена других вычисляемых полей — допускается обращение только к полям набора данных.
Для расчета долей относительно вышестоящих группировок рекомендуется использовать системную функцию СКД ВычислитьВыражение.