Как правильно вычислить разность числовых полей в запросе 1С и избежать пустых результатов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке запросов в системе «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда арифметические операции (например, вычитание одного поля из другого) возвращают пустую строку или неожиданный результат. Казалось бы, простая операция Поле1 - Поле2 должна работать безотказно, но на практике в этот процесс вмешиваются особенности типизации, обработка NULL и логика работы СУБД. В данной статье мы подробно разберем, почему возникают такие ошибки и как составить идеальное выражение для вычисления разности.

Анализ проблемы: почему стандартный подход не сработал?

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


ВЫБОР 
    КОГДА ТИПЗНАЧЕНИЯ(ВТ.Поле1) = ТИП(ЧИСЛО) 
        ТОГДА ВЫБОР 
            КОГДА ВТ.Поле1 > ВТ.Поле2 
                ТОГДА (ВЫРАЗИТЬ(ВТ.Поле1 КАК ЧИСЛО)) - (ВЫРАЗИТЬ(ВТ.Поле2 КАК ЧИСЛО)) 
            ИНАЧЕ ЛОЖЬ 
        КОНЕЦ 
    ИНАЧЕ ЛОЖЬ 
КОНЕЦ

На выходе разработчик получал пустое значение (пустую строку). Давайте проанализируем этот код и выясним, в чем кроются критические ошибки.

Причина 1: Смешивание типов в конструкции ВЫБОР

Важный момент: результат колонки в запросе определяется на основании всех возможных веток оператора ВЫБОР. Если хотя бы в одной ветке (например, в ИНАЧЕ) возвращается значение типа Булево (в нашем примере — ЛОЖЬ), а в другой — Число, система создает колонку составного типа.

Когда платформа 1С пытается вывести результат такого запроса в отчет или динамический список, она может столкнуться с трудностями интерпретации. Сочетание чисел и логических значений часто приводит к тому, что ячейка визуально выглядит пустой.

Решение: Все ветки оператора ВЫБОР должны возвращать данные одного и того же типа. Если вы ожидаете числовой результат, замените ЛОЖЬ на 0.

Причина 2: Коварство значений NULL

В языке запросов 1С любая арифметическая операция с участием NULL (например, Число - NULL или NULL + Число) всегда возвращает NULL. В интерфейсе пользователя NULL по умолчанию отображается как пустая строка.

Даже если вам кажется, что поля «не пустые», они могут содержать NULL в следующих случаях:

Проверка ТИПЗНАЧЕНИЯ(Поле) = ТИП(ЧИСЛО) вернет ЛОЖЬ, если в поле содержится NULL, и запрос уйдет в ветку ИНАЧЕ, возвращая наше некорректное ЛОЖЬ.

Разберем правильные варианты решения

Проанализируем наиболее эффективные способы вычисления разности, предложенные опытными разработчиками.

Вариант 1: Использование функции ЕСТЬNULL (рекомендуемый)

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

ЕСТЬNULL(ВТ.Поле1, 0) - ЕСТЬNULL(ВТ.Поле2, 0)

Этот код гарантирует, что даже если одно из полей окажется не заполнено, система произведет вычитание из нуля или вычитание нуля, сохранив числовой тип результата.

Вариант 2: Комплексная проверка с ВЫБОР

Если вам необходимо соблюсти условие, при котором разность считается только тогда, когда первое число больше второго, используйте следующую конструкцию:


ВЫБОР 
    КОГДА ЕСТЬNULL(ВТ.Поле1, 0) > ЕСТЬNULL(ВТ.Поле2, 0) 
        ТОГДА ЕСТЬNULL(ВТ.Поле1, 0) - ЕСТЬNULL(ВТ.Поле2, 0) 
    ИНАЧЕ 0 
КОНЕЦ

Обратите внимание: мы заменили ЛОЖЬ на 0, чтобы колонка оставалась строго числовой.

Нюансы использования ВЫРАЗИТЬ

Рассмотрим подробнее функцию ВЫРАЗИТЬ. Многие новички пытаются использовать её для преобразования типов (как CAST в SQL), но в 1С она работает иначе. Для чисел ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)) используется для ограничения разрядности и округления.

Если поле имеет составной тип и в нем лежит, к примеру, ссылка, то ВЫРАЗИТЬ вернет NULL. Поэтому использование ВЫРАЗИТЬ не заменяет проверку на NULL, а иногда даже усложняет ситуацию.

Как провести диагностику (отладку) в запросе?

Если вы по-прежнему не видите результат, выполните «проверочный» запрос. Выведите промежуточные данные, чтобы понять, что именно видит система. Разберем этот прием:


ВЫБРАТЬ
    ВТ.Поле1 КАК ИсходноеПоле1,
    ТИПЗНАЧЕНИЯ(ВТ.Поле1) КАК Тип1,
    ВТ.Поле2 КАК ИсходноеПоле2,
    ТИПЗНАЧЕНИЯ(ВТ.Поле2) КАК Тип2,
    ЕСТЬNULL(ВТ.Поле1, 0) - ЕСТЬNULL(ВТ.Поле2, 0) КАК Результат
ИЗ
    ВТ КАК ВТ

Проанализировав такую таблицу, вы сразу увидите, где появляется NULL или тип, отличный от ожидаемого (например, Неопределено или Пустая ссылка).

Влияние Системы компоновки данных (СКД)

Если ваш запрос работает правильно в консоли запросов, но выдает пустоту в отчете СКД, выясним причину в настройках оформления. В СКД есть параметр «Не выводить нулевые значения». Если результат вычитания равен нулю и эта галочка установлена, ячейка будет абсолютно пустой. Проверьте вкладку «Наборы данных» и «Условное оформление» в вашем отчете.

Итоги и рекомендации

Подводя итог, выделим золотые правила арифметики в запросах 1С:

  1. Всегда используйте ЕСТЬNULL. Это защитит расчет от «обнуления» всего выражения.
  2. Соблюдайте единообразие типов. В операторе ВЫБОР все возвращаемые значения должны быть одного типа (числа к числам, строки к строкам).
  3. Не используйте ЛОЖЬ как значение по умолчанию для чисел. Используйте 0.
  4. Проверяйте составные типы. Если поле может содержать и число, и ссылку, сначала убедитесь в типе значения, а затем выполняйте расчет, предварительно обработав NULL.

Следуя этим правилам, вы обеспечите стабильную работу ваших запросов и корректное отображение данных в любых интерфейсах системы.

← На главную