В процессе разработки отчетов и обработок на платформе 1С программисты часто сталкиваются с ситуацией, когда математическая формула в запросе выдает пустой результат или вовсе игнорирует заданные условия. Особенно часто это проявляется при расчете относительных показателей, таких как КоличествоДнейВПродаже, Оборачиваемость или СрокПоступления. Рассмотрим подробно, почему стандартное условие КОГДА Поле = 0 может не срабатывать и как правильно обрабатывать данные, чтобы избежать «исчезновения» результатов.
Проанализируем ситуацию, когда при значении колонки КПоступлению, равном нулю, расчетное поле перестает вычисляться. На первый взгляд логика кажется верной: мы проверяем равенство нулю и выполняем деление. Однако в языке запросов 1С, который базируется на SQL, существует принципиальная разница между числом 0 и значением NULL.
NULL — это специальный маркер, обозначающий отсутствие данных. Он часто появляется в результате использования конструкции ЛЕВОЕ СОЕДИНЕНИЕ, когда в правой таблице не нашлось соответствующей записи. Важно запомнить ключевое правило: любая арифметическая операция с NULL (сложение, вычитание, умножение или деление) всегда возвращает NULL.
Выясним причину на примере: если наше поле СДП (Среднедневные продажи) содержит NULL, то попытка выполнить операцию Остаток / СДП приведет к тому, что весь результат станет NULL. При этом визуально в консоли запросов или в отчете это может выглядеть как пустое поле или ноль, что сбивает разработчика с толку.
Разберем по шагам, почему обычная проверка на равенство не всегда помогает. В запросах 1С мы можем столкнуться с тремя видами «пустоты»:
Если мы напишем условие КОГДА Таблица.Поле = 0, а в поле на самом деле находится NULL, то результат сравнения будет не «Истина» и не «Ложь», а «Unknown» (Неизвестно). В итоге ветка ТОГДА просто пропускается, и система переходит к блоку ИНАЧЕ или возвращает NULL.
Посмотрим на наиболее эффективный способ решения проблемы. Для того чтобы наши формулы работали корректно, необходимо «принудительно» преобразовывать все потенциальные NULL в реальные числа (например, в ноль) еще до начала вычислений. Для этого в платформе предусмотрена функция ЕСТЬNULL.
Рассмотрим правильный пример подготовки данных в секции ВЫБРАТЬ:
ВЫБРАТЬ
ЕСТЬNULL(ЗаказыПоставщикамОстатки.ЗаказаноОстаток, 0) КАК КПоступлению,
ЕСТЬNULL(ТаблицаСДП.СреднедневныеПродажи, 0) КАК СДП,
ТаблицаОстатки.Остаток КАК Остаток
Используя такую конструкцию, мы гарантируем, что даже если данных по заказам или продажам нет, мы получим число 0, с которым запрос умеет работать предсказуемо.
Теперь проанализируем ситуацию с делением. Ошибка «Деление на 0» в запросе 1С является критической и прерывает выполнение всего кода. Однако деление на NULL ошибки не вызывает — оно просто «тихо» возвращает NULL. Это еще одна причина, по которой данные могут пропадать бесследно.
Чтобы формула КоличествоДнейВПродаже работала корректно при любом раскладе, объединим проверку на NULL и проверку на 0 внутри конструкции ВЫБОР. Рассмотрим финальный вариант формулы:
ВЫБОР
КОГДА ТаблицаОстатки.КПоступлению = 0
И ЕСТЬNULL(ТаблицаОстатки.СДП, 0) <> 0
ТОГДА ТаблицаОстатки.Остаток / ТаблицаОстатки.СДП
ИНАЧЕ 0
КОНЕЦ КАК КоличествоДнейВПродаже
В данном примере мы сначала убеждаемся, что СДП не является NULL (превращая его в 0 через ЕСТЬNULL), а затем проверяем, что полученный результат не равен нулю, чтобы избежать математической ошибки деления.
Проанализируем несколько ситуаций, в которых разработчики часто допускают промахи:
ЕСТЬNULL(Остаток / СДП, 0) не спасет от ошибки деления на ноль, если СДП равен 0. Проверять нужно именно делитель.ЕСТЬ NULL или ЕСТЬNULL().ВЫБОР КОГДА (например, сочетание И и ИЛИ), всегда расставляйте скобки, чтобы логика вычислений была однозначной.Стоит отметить, что функция ЕСТЬNULL работает быстрее, чем аналогичная конструкция ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА 0 ИНАЧЕ Поле КОНЕЦ. На больших объемах данных это может быть критично. Однако помните об особенности: ЕСТЬNULL приводит результат к типу первого аргумента. Если вы работаете с числами, проблем не возникнет, но при работе со строками разной длины возможна обрезка данных.
Для отладки сложных формул мы рекомендуем выводить промежуточные значения в результат запроса. Например, создайте временную колонку ТЕСТ_СДП_НА_NULL, в которой будет вычисляться ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА "ДА" ИНАЧЕ "НЕТ" КОНЕЦ. Это позволит быстро понять, на каком этапе данные превращаются в «пустоту».
Подводя итог, можно сказать, что стабильность формул в запросах 1С напрямую зависит от аккуратности обработки NULL. Всегда проверяйте делитель и используйте ЕСТЬNULL для всех полей, приходящих из необязательных (левых) соединений. Это обеспечит корректность ваших управленческих отчетов и избавит от загадочного исчезновения цифр в колонках.