Почему не работает формула с условием в запросе 1С при нулевых значениях?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе разработки отчетов и обработок на платформе 1С программисты часто сталкиваются с ситуацией, когда математическая формула в запросе выдает пустой результат или вовсе игнорирует заданные условия. Особенно часто это проявляется при расчете относительных показателей, таких как КоличествоДнейВПродаже, Оборачиваемость или СрокПоступления. Рассмотрим подробно, почему стандартное условие КОГДА Поле = 0 может не срабатывать и как правильно обрабатывать данные, чтобы избежать «исчезновения» результатов.

Разбираем причину проблемы: коварство NULL

Проанализируем ситуацию, когда при значении колонки КПоступлению, равном нулю, расчетное поле перестает вычисляться. На первый взгляд логика кажется верной: мы проверяем равенство нулю и выполняем деление. Однако в языке запросов 1С, который базируется на SQL, существует принципиальная разница между числом 0 и значением NULL.

NULL — это специальный маркер, обозначающий отсутствие данных. Он часто появляется в результате использования конструкции ЛЕВОЕ СОЕДИНЕНИЕ, когда в правой таблице не нашлось соответствующей записи. Важно запомнить ключевое правило: любая арифметическая операция с NULL (сложение, вычитание, умножение или деление) всегда возвращает NULL.

Выясним причину на примере: если наше поле СДП (Среднедневные продажи) содержит NULL, то попытка выполнить операцию Остаток / СДП приведет к тому, что весь результат станет NULL. При этом визуально в консоли запросов или в отчете это может выглядеть как пустое поле или ноль, что сбивает разработчика с толку.

Отличие NULL от «Неопределено» и пустой строки

Разберем по шагам, почему обычная проверка на равенство не всегда помогает. В запросах 1С мы можем столкнуться с тремя видами «пустоты»:

  1. 0 — числовое значение. С ним работают обычные операторы сравнения.
  2. Неопределено — значение соответствующего типа 1С. В запросе оно встречается редко, обычно в полях составного типа.
  3. NULL — отсутствие значения в базе данных.

Если мы напишем условие КОГДА Таблица.Поле = 0, а в поле на самом деле находится NULL, то результат сравнения будет не «Истина» и не «Ложь», а «Unknown» (Неизвестно). В итоге ветка ТОГДА просто пропускается, и система переходит к блоку ИНАЧЕ или возвращает NULL.

Решение №1: Использование функции ЕСТЬNULL

Посмотрим на наиболее эффективный способ решения проблемы. Для того чтобы наши формулы работали корректно, необходимо «принудительно» преобразовывать все потенциальные NULL в реальные числа (например, в ноль) еще до начала вычислений. Для этого в платформе предусмотрена функция ЕСТЬNULL.

Рассмотрим правильный пример подготовки данных в секции ВЫБРАТЬ:


ВЫБРАТЬ
    ЕСТЬNULL(ЗаказыПоставщикамОстатки.ЗаказаноОстаток, 0) КАК КПоступлению,
    ЕСТЬNULL(ТаблицаСДП.СреднедневныеПродажи, 0) КАК СДП,
    ТаблицаОстатки.Остаток КАК Остаток

Используя такую конструкцию, мы гарантируем, что даже если данных по заказам или продажам нет, мы получим число 0, с которым запрос умеет работать предсказуемо.

Решение №2: Правильная обработка деления на ноль

Теперь проанализируем ситуацию с делением. Ошибка «Деление на 0» в запросе 1С является критической и прерывает выполнение всего кода. Однако деление на NULL ошибки не вызывает — оно просто «тихо» возвращает NULL. Это еще одна причина, по которой данные могут пропадать бесследно.

Чтобы формула КоличествоДнейВПродаже работала корректно при любом раскладе, объединим проверку на NULL и проверку на 0 внутри конструкции ВЫБОР. Рассмотрим финальный вариант формулы:


ВЫБОР
    КОГДА ТаблицаОстатки.КПоступлению = 0 
          И ЕСТЬNULL(ТаблицаОстатки.СДП, 0) <> 0 
    ТОГДА ТаблицаОстатки.Остаток / ТаблицаОстатки.СДП
    ИНАЧЕ 0
КОНЕЦ КАК КоличествоДнейВПродаже

В данном примере мы сначала убеждаемся, что СДП не является NULL (превращая его в 0 через ЕСТЬNULL), а затем проверяем, что полученный результат не равен нулю, чтобы избежать математической ошибки деления.

Типичные ошибки при работе с формулами в запросах

Проанализируем несколько ситуаций, в которых разработчики часто допускают промахи:

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

Рекомендации по повышению производительности

Стоит отметить, что функция ЕСТЬNULL работает быстрее, чем аналогичная конструкция ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА 0 ИНАЧЕ Поле КОНЕЦ. На больших объемах данных это может быть критично. Однако помните об особенности: ЕСТЬNULL приводит результат к типу первого аргумента. Если вы работаете с числами, проблем не возникнет, но при работе со строками разной длины возможна обрезка данных.

Для отладки сложных формул мы рекомендуем выводить промежуточные значения в результат запроса. Например, создайте временную колонку ТЕСТ_СДП_НА_NULL, в которой будет вычисляться ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА "ДА" ИНАЧЕ "НЕТ" КОНЕЦ. Это позволит быстро понять, на каком этапе данные превращаются в «пустоту».

Подводя итог, можно сказать, что стабильность формул в запросах 1С напрямую зависит от аккуратности обработки NULL. Всегда проверяйте делитель и используйте ЕСТЬNULL для всех полей, приходящих из необязательных (левых) соединений. Это обеспечит корректность ваших управленческих отчетов и избавит от загадочного исчезновения цифр в колонках.

← На главную