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