Обязательно ли убирать NULL из запроса и как правильно работать с отсутствующими значениями

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

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

Что такое NULL и откуда он берется?

Прежде всего, давайте определим, что NULL — это не ноль, не пустая строка и даже не Неопределено. Это специальный маркер, обозначающий полное отсутствие данных. В запросах 1С NULL чаще всего появляется в результате Левого или Полного соединения таблиц, когда для записи из левой таблицы не находится соответствующей записи в правой таблице.

Рассмотрим ситуацию на примере. Допустим, мы соединяем таблицу «Продажи» с таблицей «Скидки» по полю Номенклатура. Если на какой-то товар скидка не установлена, в колонке со значением скидки мы получим NULL. Проанализируем, к чему это приведет при дальнейших расчетах.

Главная ловушка: NULL ничему не равен

Самая распространенная ошибка — попытка сравнить NULL с чем-либо (даже с другим NULL) с помощью обычного оператора равенства. Проанализируем логику СУБД: выражение NULL = NULL вернет не ИСТИНА, а UNKNOWN (неизвестно), что в условиях фильтрации ГДЕ ведет себя аналогично значению ЛОЖЬ.

Если нам нужно проверить поле на наличие этого значения, мы должны использовать специальную конструкцию:


ГДЕ
    Таблица.Поле ЕСТЬ NULL

Или наоборот, если мы хотим исключить пустые связи:


ГДЕ
    НЕ Таблица.Поле ЕСТЬ NULL

Трехзначная логика SQL

Разберем подробнее, как работают логические операции, когда в них замешан NULL. Это критично для понимания того, как будет вести себя ваш запрос:

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

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


ВЫБРАТЬ
    Продажи.Номенклатура,
    ЕСТЬNULL(Продажи.Количество, 0) КАК Количество
ИЗ
    РегистрНакопления.Продажи КАК Продажи

Важно помнить о приведении типов при использовании этой функции. ЕСТЬNULL ограничивает тип результата типом первого аргумента. Если Поле имеет тип Строка(10), а в качестве замены вы укажете строку длиной 20 символов, то значение будет обрезано до 10 символов. Рассмотрим ситуацию, когда ЕСТЬNULL работает быстрее, чем конструкция ВЫБОР КОГДА ... ТОГДА, так как она транслируется напрямую в нативную функцию СУБД.

Влияние на арифметику и агрегатные функции

Выясним причину, почему математические операции с NULL могут «сломать» ваш отчет. Любая операция сложения, вычитания или конкатенации строк с участием NULL дает NULL.

Например: 100 + NULL = NULL. Если в вашем запросе вы суммируете показатели из разных таблиц, обязательно оборачивайте их в ЕСТЬNULL, иначе отсутствие данных в одной колонке обнулит всю строку.

С агрегатными функциями ситуация иная:

  1. СУММА, СРЕДНЕЕ, МИНИМУМ — игнорируют NULL. Они рассчитывают результат только по тем строкам, где значения заполнены.
  2. КОЛИЧЕСТВО(Поле) — посчитает только непустые значения.
  3. КОЛИЧЕСТВО(*) — посчитает все строки, даже если они целиком состоят из NULL.

Производительность и индексы

Проанализируем вопрос производительности. Использование функции ЕСТЬNULL в секции ГДЕ может существенно замедлить запрос. Это происходит потому, что СУБД не может эффективно использовать индексы по полю, обернутому в функцию (запрос становится non-SARGable).

Плохой вариант:


ГДЕ
    ЕСТЬNULL(СуммаОстаток, 0) > 100

В этом случае СУБД придется выполнить сканирование всей таблицы (Full Table Scan).

Хороший вариант:


ГДЕ
    СуммаОстаток > 100
    ИЛИ СуммаОстаток ЕСТЬ NULL

Такой подход позволяет оптимизатору использовать индекс по полю СуммаОстаток.

NULL против Неопределено

Часто возникает путаница между этими понятиями. Проанализируем отличия:

Выводы: нужно ли убирать NULL?

Подведем итог. Убирать NULL из запроса нужно в следующих случаях:

Однако, иногда NULL полезен. Например, когда вам нужно найти записи, для которых нет соответствия в другой таблице. В этом случае мы специально ищем NULL, чтобы понять, какие данные отсутствуют.

← На главную