При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда формула вычисляемого поля вида ((Поле1 + Поле2) / (Поле3 + Поле4)) приводит к ошибке «Деление на 0» во всех или некоторых строках отчета. При этом исходные данные могут казаться корректными, а сумма полей знаменателя визуально никогда не равна нулю.
Проанализируем природу этой ошибки, выясним, почему механизм СКД возвращает деление на ноль, и разберем надежные способы исправления ситуации.
Выделим ключевые причины, из-за которых СКД выдает ошибку деления на ноль при вычислении выражений:
NULL в исходных полях: Если числовые поля приходят из левых соединений запроса или пустых реквизитов, они содержат значение NULL, а не числовой 0. Любая арифметическая операция со значением NULL (например, NULL + 0) в выражениях СКД приводит к неопределенному результату или ошибке приведения типов, что в операции деления провоцирует ошибку «Деление на 0».NULL, что сразу вызывает ошибку.NULL, отчет выдаст ошибку.Разберем базовое решение проблемы непосредственно в выражении вычисляемого поля. Нам необходимо обернуть каждое числовое поле в функцию ЕСТЬNULL() с подстановкой нуля, а также добавить явную проверку знаменателя через конструкцию ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ.
Перейдем на вкладку «Вычисляемые поля» и укажем следующее выражение для поля:
ВЫБОР
КОГДА (ЕСТЬNULL(Поле3, 0) + ЕСТЬNULL(Поле4, 0)) = 0 ТОГДА 0
ИНАЧЕ (ЕСТЬNULL(Поле1, 0) + ЕСТЬNULL(Поле2, 0)) / (ЕСТЬNULL(Поле3, 0) + ЕСТЬNULL(Поле4, 0))
КОНЕЦ
Посмотрим, как работает данная конструкция: если сумма знаменателя после замены всех NULL на ноль оказывается равной нулю, система возвращает 0, предотвращая аварийное деление.
Рассмотрим более производительный вариант. Перенос обработки NULL на уровень СУБД снижает нагрузку на процессор компоновки данных и исключает проблемы с неопределенными типами данных.
В тексте запроса набора данных оборачиваем числовые поля функцией ЕСТЬNULL:
ВЫБРАТЬ
ЕСТЬNULL(Таблица.Поле1, 0) КАК Поле1,
ЕСТЬNULL(Таблица.Поле2, 0) КАК Поле2,
ЕСТЬNULL(Таблица.Поле3, 0) КАК Поле3,
ЕСТЬNULL(Таблица.Поле4, 0) КАК Поле4
ИЗ
РегистрНакопления.Продажи КАК Таблица
После такой подготовки в вычисляемом поле СКД достаточно оставить только проверку деления на ноль:
ВЫБОР
КОГДА (Поле3 + Поле4) = 0 ТОГДА 0
ИНАЧЕ (Поле1 + Поле2) / (Поле3 + Поле4)
КОНЕЦ
Если рассчитываемый показатель является относительным коэффициентом или долей и должен выводиться в итоговых строках отчета, его категорически нельзя просто суммировать. Сумма отношений не равна отношению сумм.
Разберем правильную настройку ресурса по шагам:
Сумма():
ВЫБОР
КОГДА (Сумма(Поле3) + Сумма(Поле4)) = 0 ТОГДА 0
ИНАЧЕ (Сумма(Поле1) + Сумма(Поле2)) / (Сумма(Поле3) + Сумма(Поле4))
КОНЕЦ
При такой настройке СКД сначала просуммирует значения полей для текущей группировки и только затем выполнит безопасное деление, что гарантирует математическую корректность итогов и отсутствие деления на ноль.
Если в конфигурации уже присутствуют стандартные библиотеки (например, БСП), мы можем воспользоваться готовыми сервисными функциями деления, вызывая их прямо из выражения СКД:
ОбщегоНазначенияКлиентСервер.Разделить(Поле1 + Поле2, Поле3 + Поле4)
Такая функция внутри себя содержит проверку делителя на ноль и корректно обрабатывает пустые значения, делая формулу в схеме компоновки компактной и легко читаемой.