Работа с NULL-значениями в запросах 1С:Предприятие часто становится источником ошибок даже для опытных разработчиков. Оператор ЕстьNull — один из ключевых инструментов для обработки таких ситуаций, но его поведение не всегда интуитивно понятно. В отличие от стандартного SQL, где используется IS NULL или COALESCE, в реализована собственная логика работы с пустыми значениями, что требует отдельного изучения.

Эта статья поможет разобраться, как именно функционирует ЕстьNull в различных сценариях: от простых проверок на пустоту до сложных выражений с вложенными запросами. Мы рассмотрим не только синтаксис, но и скрытые нюансы производительности, которые могут влиять на скорость выполнения запросов в крупных базах данных. Особое внимание уделим типичным ошибкам, которые приводят к некорректным результатам или даже падению системы.

Материал будет полезен как бухгалтерам, которые самостоятельно пишут отчёты в 1С:Бухгалтерии, так и разработчикам, оптимизирующим сложные интеграционные решения. Все примеры приведены для актуальных версий платформы (8.3.20+), но основные принципы остаются неизменными с момента появления этого оператора.

Что такое NULL в контексте 1С и почему его нельзя игнорировать

В 1С:Предприятие NULL — это специальное значение, обозначающее отсутствие данных. Оно принципиально отличается от пустой строки (""), нуля (0) или даты '00010101'. NULL может появляться в следующих случаях:

  • 📌 В полях базы данных, которые не были заполнены (например, не указан телефон контрагента)
  • 🔄 При левых соединениях (ЛЕВОЕ СОЕДИНЕНИЕ), когда в правой таблице нет соответствующих записей
  • 🧮 В результатах вычисляемых полей, где одно из значений отсутствует (например, Сумма / Количество при нулевом количестве)
  • 🔍 При использовании функций агрегации по пустым группам (например, СУММА() по несуществующему разделу)

Ключевая особенность NULL в — это его "заразность". Любая операция с участием NULL (кроме специальных функций вроде ЕстьNull) вернёт NULL. Например:


ВЫБРАТЬ

10 + NULL КАК РезультатСложения, // Вернёт NULL

"Текст" + NULL КАК РезультатКонкатенации // Вернёт NULL

⚠️ Внимание: В отличие от SQL, где NULL = NULL возвращает UNKNOWN, в сравнение Значение = NULL всегда даёт ЛОЖЬ, даже если Значение действительно равно NULL. Для проверки нужно использовать Значение ЕСТЬ NULL.

Синтаксис и базовые примеры использования ЕстьNull

Оператор ЕстьNull имеет простой синтаксис:

ЕстьNull(Выражение1, Выражение2)

Логика работы:

  1. Если Выражение1 не равно NULL, возвращается Выражение1
  2. Если Выражение1 равно NULL, возвращается Выражение2

Классический пример — подстановка нуля вместо NULL в финансовых расчётах:


ВЫБРАТЬ

ЕстьNull(СуммаДокумента, 0) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг

Важно понимать, что ЕстьNull — это не функция, а оператор языка запросов. Он обрабатывается на этапе выполнения запроса, а не после получения результатов. Это влияет на план выполнения и может быть критично для производительности.

📊 Как часто вы используете ЕстьNull в запросах?
Постоянно
Иногда
Редеко
Никогда
Не знаю, что это

Разница между ЕстьNull и конструкцией ВЫБОР КОГДА

Многие разработчики ошибочно считают, что ЕстьNull и ВЫБОР КОГДА.. ТОГДА взаимозаменяемы. На практике между ними есть принципиальные различия:

Критерий ЕстьNull ВЫБОР КОГДА
Производительность Выше (обрабатывается на уровне оптимизатора запросов) Ниже (вычисляется для каждой строки результата)
Читаемость кода Лаконичнее для простых подстановок Гибче для сложной логики
Поддержка вложенных выражений Ограничена (только два аргумента) Неограничена (можно использовать многоуровневые условия)
Работа с типами данных Автоматическое приведение типов Требует явного приведения в сложных случаях

Пример, где ВЫБОР КОГДА предпочтительнее:


ВЫБРАТЬ

ВЫБОР

КОГДА СуммаДокумента ЕСТЬ NULL

ТОГДА 0

КОГДА СуммаДокумента < 0

ТОГДА СуммаДокумента * -1

ИНАЧЕ СуммаДокумента

КОНЕЦ КАК КорректированнаяСумма

💡

Для проверки на NULL в условиях WHERE всегда используйте конструкцию Поле ЕСТЬ NULL или Поле НЕ ЕСТЬ NULL — это гарантирует корректную работу с индексами.

Типичные ошибки при работе с ЕстьNull и как их избежать

Даже опытные разработчики допускают ошибки при использовании ЕстьNull. Вот наиболее распространённые ловушки:

  • 🔥 Игнорирование типов данных: ЕстьNull(ЧисловоеПоле, "") приведёт к ошибке приведения типов. Всегда используйте совместимые типы или явное приведение: ЕстьNull(ЧисловоеПоле, 0)
  • 🔄 Неправильная обработка дат: ЕстьNull(ДатаДокумента, '00010101') может вызвать проблемы при сравнении. Лучше использовать НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()) или другое осмысленное значение
  • 📊 Избыточное использование: Применение ЕстьNull ко всем полям в большом запросе может значительно замедлить его выполнение. Используйте только там, где действительно необходима обработка NULL
  • 🔍 Путаница с пустыми строками: ЕстьNull(Поле, "") и ВЫБОР КОГДА Поле = "" ТОГДА "ЗначениеПоУмолчанию" — это разные вещи! NULL ≠ пустая строка

Особенно опасна ошибка с типами данных в запросах, которые используются в отчётах с СКД. Например, если в поле с числовым типом попадёт строка из-за некорректного ЕстьNull, это может привести к падению при построении отчёта.

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

Оптимизация запросов с ЕстьNull: советы для крупных баз данных

В системах с миллионами записей неоптимальное использование ЕстьNull может приводить к значительным задержкам. Вот ключевые рекомендации по оптимизации:

  1. Избегайте ЕстьNull в условиях WHERE. Запрос вида ГДЕ ЕстьNull(Поле, 0) > 100 не может использовать индексы. Лучше разделить на два запроса с Поле > 100 и Поле ЕСТЬ NULL
  2. Используйте ЕстьNull только для конечных полей. Применение в промежуточных вычислениях (например, в подзапросах) увеличивает нагрузку
  3. Для часто используемых подстановок создавайте вычисляемые поля в виртуальных таблицах вместо повторяющегося ЕстьNull в основных запросах
  4. Анализируйте план выполнения. В консоли запросов можно увидеть, как именно обрабатывается ЕстьNull — иногда оптимизатор заменяет его на более эффективные конструкции

Пример оптимизированного запроса для отчёта по продажам:


ВЫБРАТЬ

Товар,

ЕстьNull(СУММА(Количество), 0) КАК ОбщееКоличество,

ЕстьNull(СУММА(Сумма), 0) КАК ОбщаяСумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары

ГДЕ

Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО

Товар

Убедиться, что типы данных в ЕстьNull совместимы|Проверить наличие индексов для полей в WHERE|Оценить необходимость ЕстьNull для каждого поля|Протестировать запрос на небольшом объёме данных-->

Продвинутые техники: ЕстьNull в соединениях и подзапросах

Оператор ЕстьNull особенно полезен при работе со сложными соединениями таблиц, где NULL-значения могут искажать результаты. Рассмотрим несколько нетривиальных примеров:

1. Левое соединение с подстановкой значений по умолчанию:


ВЫБРАТЬ

К.Наименование КАК Контрагент,

ЕстьNull(Д.СуммаДокумента, 0) КАК СуммаЗаказов

ИЗ

Справочник.Контрагенты КАК К

ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказыПокупателей КАК Д

ПО К.Ссылка = Д.Контрагент

ГДЕ

Д.Дата МЕЖДУ &Начало И &Конец

2. Обработка NULL в подзапросах:


ВЫБРАТЬ

Товар,

(ВЫБРАТЬ

ЕстьNull(МАКСИМУМ(Цена), 0)

ИЗ

Документ.УстановкаЦенНоменклатуры

ГДЕ

Номенклатура = ВНЕШНЯЯТАБЛИЦА.Товар) КАК ПоследняяЦена

ИЗ

Справочник.Номенклатура КАК Товар

3. Комбинирование с другими функциями:


ВЫБРАТЬ

ЕстьNull(РАЗНОСТЬДАТ(ДатаОплаты, ДатаДокумента, ДЕНЬ), 0) КАК ДнейМеждуОплатой

Особенно мощной становится комбинация ЕстьNull с ВЫРАЗИТЬ для приведения типов:


ВЫБРАТЬ

ЕстьNull(ВЫРАЗИТЬ(СтрокаКакЧисло КАК ЧИСЛО(10,2)), 0) КАК ЧисловоеЗначение

Как ЕстьNull взаимодействует с виртуальными таблицами?

В виртуальных таблицах (например, Документ.РеализацияТоваровУслуг.Обороты) NULL-значения могут появляться для периодов без движений. Оператор ЕстьNull в таких случаях работает корректно, но Например, в запросе к оборотной ведомости использование ЕстьNull(Количество, 0) не повлияет на производительность, так как NULL там появляются только для отсутствующих записей, которые всё равно не попадают в результат без явного ЛЕВОГО СОЕДИНЕНИЯ.

Альтернативные подходы: когда ЕстьNull не лучший выбор

Несмотря на удобство, ЕстьNull не всегда является оптимальным решением. Рассмотрим альтернативы для разных сценариев:

1. Для сложной логики подстановки: Используйте ВЫБОР КОГДА с несколькими условиями. Например, когда нужно подставлять разные значения в зависимости от контекста:


ВЫБРАТЬ

ВЫБОР

КОГДА Сумма ЕСТЬ NULL ТОГДА 0

КОГДА Сумма < 0 ТОГДА Сумма * -1

ИНАЧЕ Сумма

КОНЕЦ КАК КорректированнаяСумма

2. Для обработки NULL в агрегатных функциях: В некоторых случаях эффективнее использовать СУММА(ЕстьNull(Поле, 0)), но для СРЕДНЕЕ() лучше предварительно отфильтровать NULL-значения:


ВЫБРАТЬ

СРЕДНЕЕ(Сумма) КАК СредняяСумма

ИЗ

Документ.РеализацияТоваровУслуг

ГДЕ

Сумма НЕ ЕСТЬ NULL

3. Для работы с иерархиями: При выборке иерархических данных (например, группы номенклатуры) иногда удобнее использовать ПУСТАЯ ССЫЛКА() вместо ЕстьNull:


ВЫБРАТЬ

ЕстьNull(Родитель, ПУСТАЯ ССЫЛКА(Справочник.Номенклатура)) КАК Родитель

4. В временных таблицах: Если вы создаёте временную таблицу для сложных расчётов, имеет смысл заранее заменить NULL на значения по умолчанию, чтобы не использовать ЕстьNull в каждом последующем запросе.

💡

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

FAQ: Частые вопросы по работе с ЕстьNull в 1С

Можно ли использовать ЕстьNull в выражениях для отбора (WHERE)?

Технически можно, но это крайне не рекомендуется. Конструкция вида ГДЕ ЕстьNull(Поле, 0) > 100 не позволяет использовать индексы, так как оптимизатор не может заранее определить, какие значения будут подставлены вместо NULL. Лучше разделить условие на два:

ГДЕ (Поле > 100) ИЛИ (Поле ЕСТЬ NULL)

Или, если логика другая:

ГДЕ (Поле ЕСТЬ NULL) ИЛИ (Поле > 100)
Почему ЕстьNull(Дата, ТекущаяДата()) иногда возвращает неожиданные результаты?

Проблема обычно связана с неявным приведением типов. Если поле Дата имеет тип ДатаВремя, а вы подставляете просто Дата, может происходить автоматическое преобразование, которое обрезает время. Всегда явно приводите типы:

ЕстьNull(Дата, НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()))

Или, если нужно сохранить время:

ЕстьNull(Дата, ТЕКУЩАЯДАТА())
Как ЕстьNull работает с полями типа ХранилищеЗначения?

Для полей типа ХранилищеЗначения (например, в регистрах сведений) ЕстьNull ведёт себя стандартно, но важно помнить, что:

  • Пустое хранилище ≠ NULL (пустое хранилище — это объект с нулевой длиной)
  • Для проверки на пустоту хранилища используйте Значение.Пустая()
  • ЕстьNull не может создать новое хранилище — только подставить существующее

Пример корректной обработки:


ВЫБРАТЬ

ЕстьNull(Данные, НОВЫЙ ХранилищеЗначения("")) КАК Данные

Влияет ли ЕстьNull на производительность в больших базах данных?

Да, но степень влияния зависит от контекста:

  • В простых запросах с индексированными полями — влияние минимально
  • В запросах с полным перебором таблиц — может увеличивать время выполнения на 10-30%
  • В подзапросах — может приводить к многократному вычислению выражения

Для критичных по производительности запросов:

  • Заменяйте ЕстьNull на явные условия в WHERE
  • Используйте временные таблицы для предварительной обработки NULL
  • Тестируйте запрос с включённым планом выполнения
Можно ли использовать ЕстьNull в запросах к внешним источникам данных (Federated Tables)?

В запросах к внешним источникам (например, через Универсальный обмен данными или Federated Tables в PostgreSQL) поведение ЕстьNull зависит от:

  • Типа подключения (ODBC, HTTP-сервис, прямая работа с СУБД)
  • Версии платформы 1С (в 8.3.20+ поддержка лучше)
  • Типов данных внешнего источника

Рекомендации:

  • Всегда тестируйте запрос на небольшом объёме данных
  • Явно приводите типы данных в ЕстьNull
  • Для критических интеграций обрабатывайте NULL на стороне источника
⚠️ Внимание: При работе с внешними источниками через ODBC оператор ЕстьNull может транслироваться в COALESCE или ISNULL в зависимости от СУБД, что иногда приводит к неожиданным результатам.