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