К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как убрать пустые значения в запросе 1С

Как убрать пустые значения в запросе 1С: отбор по NULL, пустым ссылкам и строкам, ЕСТЬ NULL, ВЫБОР, ГДЕ. Примеры кода, типичные ошибки и проверка результата.

Пустые значения в результате запроса 1С — одна из самых частых причин «битых» отчётов: в строках появляются пропуски, итоги считаются не так, как ожидается, а при выгрузке в Excel или СКД пустые ячейки мешают дальнейшей обработке. Причём «пустое значение» в 1С — не одно понятие, а целое семейство: NULL, пустая ссылка справочника или документа, пустая строка, пустая дата, незаполненное значение перечисления. Каждый тип требует своего способа отбора.

Главная ошибка разработчиков — пытаться отфильтровать всё одним условием вида ГДЕ Поле <> NULL. Такая конструкция не сработает: NULL в языке запросов 1С нельзя сравнивать операторами равенства и неравенства, для него существует отдельный оператор ЕСТЬ NULL. А пустая ссылка и NULL — вообще разные сущности, хотя визуально в отчёте выглядят одинаково.

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

Какие бывают пустые значения в 1С и почему это важно

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

Второй вид — пустая ссылка. Это реальное значение ссылочного типа, которое хранится в базе данных: реквизит заполнен, но ссылается «в никуда». Третий — пустая строка ("") и четвёртый — пустая дата ('00010101'). Оба хранятся как обычные значения и сравниваются обычными операторами.

Практический признак: если пустое значение появилось только после добавления ЛЕВОГО СОЕДИНЕНИЯ — почти наверняка это NULL. Если пустота видна и при обращении к одной таблице без соединений — скорее всего, это пустая ссылка, пустая строка или незаполненный реквизит.

Как отфильтровать NULL через оператор ЕСТЬ NULL

Для исключения строк с NULL используется конструкция ГДЕ НЕ Поле ЕСТЬ NULL. Это единственный корректный способ проверки. Условие ГДЕ Поле <> NULL синтаксически допустимо, но всегда вернёт «ложь» для NULL-значений и фактически не отфильтрует ничего осмысленного — а при сравнении Поле = NULL вы потеряете вообще все строки с NULL, даже если ожидали обратного.

Типовой пример — отбор контрагентов, у которых заполнен договор:

ВЫБРАТЬ

Контрагенты.Ссылка КАК Контрагент,

Договоры.Ссылка КАК Договор

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК Договоры

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

ГДЕ

НЕ Договоры.Ссылка ЕСТЬ NULL

Заметьте: такая конструкция по смыслу эквивалентна внутреннему соединению. Если вам нужны только строки с совпадениями, проще сразу написать ВНУТРЕННЕЕ СОЕДИНЕНИЕ — запрос будет понятнее и, как правило, быстрее. ЛЕВОЕ СОЕДИНЕНИЕ с фильтром «НЕ ЕСТЬ NULL» оправдано, только когда условие сложнее или соединений несколько.

Как убрать пустые ссылки, строки и даты

Пустая ссылка отбирается сравнением со значением по умолчанию конкретного типа. В языке запросов для этого есть конструкция ЗНАЧЕНИЕ():

ГДЕ Номенклатура.Поставщик <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)

Для перечислений синтаксис аналогичный: ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.ПустаяСсылка). Для документов — ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка). Важно указывать именно тот тип, который объявлен у реквизита, иначе сравнение может не сработать для составных типов.

Пустые строки и даты фильтруются обычным сравнением с литералом:

ГДЕ Товары.Комментарий <> ""

И Товары.ДатаОтгрузки <> ДАТАВРЕМЯ(1, 1, 1)

Отдельный нюанс — строки неограниченной длины. Их нельзя сравнивать напрямую в некоторых ситуациях, поэтому применяют функцию ПОДСТРОКА(Поле, 1, 1) <> "" либо проверку через ВЫРАЗИТЬ. На управляемых формах и в типовых конфигурациях такие поля встречаются, например, в дополнительных сведениях.

Если реквизит имеет составной тип (например, ссылка на несколько справочников), пустым он считается, только когда равен НЕОПРЕДЕЛЕНО или пустой ссылке одного из типов. Надёжнее проверять: ГДЕ Поле = НЕОПРЕДЕЛЕНО ИЛИ Поле = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка) — в зависимости от того, что требуется исключить.
ПЗ
Практическое замечание

Как заменить NULL на значение вместо удаления строк

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

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Товары.Ссылка = Остатки.Номенклатура

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

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

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

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

В системе компоновки данных фильтрацию можно вынести из текста запроса в настройки отчёта: на закладке «Отбор» добавьте условие «Поле — Заполнено». Это удобно, когда один и тот же запрос используется с разными вариантами отбора. Однако логика «Заполнено» в СКД учитывает и NULL, и пустые ссылки, что иногда даёт неожиданный эффект на составных типах.

Если запрос уже выполнен и данные обрабатываются в коде, пустые строки отсекают при обходе выборки:

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

Если Не ЗначениеЗаполнено(Выборка.Поставщик) Тогда

Продолжить;

КонецЕсли;

// обработка строки

КонецЦикла;

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

Способы убрать пустые значения

Секция ГДЕ в запросе

Самый быстрый вариант: строки отсекаются на уровне СУБД. Подходит, когда пустые записи не нужны нигде в результате.

ЕСТЬNULL / ВЫБОР

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

Отбор в настройках СКД

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

Проверка в коде при обходе

Универсально через ЗначениеЗаполнено(), но медленнее и грузит выборку. Оправдано при сложной логике пропуска.

Типичные ошибки и ограничения

Самая распространённая ошибка — сравнение с NULL через равенство. Запрос выполнится без ошибки, но результат будет неверным: условие Поле = NULL никогда не истинно, а Поле <> NULL отсекает NULL-строки неявно и непредсказуемо в сложных выражениях. Всегда используйте ЕСТЬ NULL.

Вторая ошибка — фильтрация по полю присоединённой таблицы в секции ГДЕ при левом соединении без учёта NULL. Условие ГДЕ Остатки.Склад = &Склад молча превратит левое соединение во внутреннее: все строки без остатков исчезнут. Если это нежелательно, условие нужно перенести в секцию ПО соединения.

Третья группа проблем — производительность. Условия вида ПОДСТРОКА(Поле, 1, 1) <> "" или сравнение с приведением типов не используют индексы и при больших объёмах данных заметно замедляют запрос. По возможности фильтруйте по полям простых типов без функций.

Типичные ошибки
01
Сравнение Поле <> NULL вместо НЕ Поле ЕСТЬ NULL — условие работает не так, как ожидается, и строки теряются или остаются
02
Условие по полю правой таблицы в ГДЕ при левом соединении — левое соединение фактически превращается во внутреннее, строки без совпадений пропадают
03
Подстановка строки вместо пустой ссылки в ЕСТЬNULL — ошибка преобразования типов при выводе в СКД
04
Проверка пустой строки без учёта строк из пробелов — значение " " формально не пустое и проходит фильтр
05
Фильтрация в коде вместо запроса на больших таблицах — лишняя нагрузка и медленная работа

Как проверить, что отбор сработал правильно

После добавления условий выполните запрос в консоли запросов и сверьте три вещи. Первое — количество строк: оно должно уменьшиться ровно на число записей с пустыми значениями, которые вы ожидали исключить. Если строк пропало больше — вероятно, условие задело лишнее (классический случай — левое соединение с фильтром в ГДЕ).

Второе — итоги по числовым полям. Сравните сумму до и после фильтрации: разница должна объясняться именно исключёнными строками. Третье — отсутствие пустых ячеек в целевой колонке результата. Если пустоты остались, значит, вы фильтровали не тот тип пустого значения: например, проверяли NULL, а в данных пустая ссылка.

Контрольные точки

Как проверить результат

Количество строк результата
Норма

Уменьшилось ровно на число строк с пустыми значениями

Тревожный признак

Строк пропало заметно больше — условие отсекает лишние данные

Колонка с бывшими пустотами
Норма

Ни одной пустой ячейки или везде значение-замена

Тревожный признак

Пустоты остались — фильтровался не тот тип значения

Итоговые суммы
Норма

Разница с исходным запросом объясняется исключёнными строками

Тревожный признак

Итоги изменились необъяснимо — проверьте соединения и группировки

Часто задаваемые вопросы

Чем NULL отличается от пустой ссылки в 1С?

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

Почему условие «Поле <> NULL» не работает?

Потому что NULL не сравнивается операторами равенства и неравенства: любое такое сравнение даёт неопределённый результат, а не Истину или Ложь. Единственный корректный способ проверки NULL в языке запросов 1С — оператор ЕСТЬ NULL в сочетании с НЕ для исключения пустых строк.

Как убрать строки, где поле заполнено пробелами?

Строка из пробелов не считается пустой, поэтому условие Поле <> "" её пропустит. Используйте сравнение после удаления пробелов: в запросе это можно сделать через ПОДСТРОКУ и проверку на пустоту, а в коде — через СокрЛП(Значение) = "". Учтите, что такие условия не используют индексы и медленнее работают на больших таблицах.

Как показать ноль вместо NULL в остатках?

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

Можно ли убрать пустые значения без изменения текста запроса?

Да, если отчёт построен на СКД: добавьте в настройках отбор «Поле — Заполнено». Пользователь сможет включать и отключать условие самостоятельно. Минус в том, что данные всё равно выбираются из базы целиком, а фильтруются при формировании отчёта, что медленнее отбора в тексте запроса.

Почему после добавления отбора пропали нужные строки?

Чаще всего причина в условии по полю присоединённой таблицы, помещённом в секцию ГДЕ при левом соединении. Для строк без совпадения это поле равно NULL, и условие их отсекает. Перенесите проверку в секцию ПО соединения либо явно разрешите NULL: ГДЕ (Поле = &Значение ИЛИ Поле ЕСТЬ NULL).

Итог

Что важно запомнить

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