Как правильно заменить NULL или пустую ссылку на другое значение в запросе СКД?

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

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

Анализ проблемы: Сравнение ссылок и строк

В исходном коде мы видим следующую конструкцию внутри запроса:


ВЫБОР 
    КОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения = "" 
    ТОГДА ... 
    ИНАЧЕ ... 
КОНЕЦ

Автор пытается проверить, заполнено ли поле ПодразделениеОрганизацииЗавершения, сравнивая его с пустой строкой (""). Это фундаментальная ошибка. В языке запросов 1С (как и во встроенном языке) действует строгая типизация. Поле ПодразделениеОрганизацииЗавершения имеет тип СправочникСсылка (например, Ссылка на справочник Подразделения). А литерал "" имеет тип Строка. При выполнении условия Ссылка = Строка система 1С всегда возвращает результат Ложь, потому что эти типы данных никогда не могут быть равны друг другу. Даже если пользователю кажется, что поле "пустое", технически там находится "Пустая ссылка", а не пустая строка. Именно поэтому условие КОГДА не срабатывает, и всегда выполняется ветка ИНАЧЕ.

Различие между NULL, Пустой ссылкой и Неопределено

Чтобы правильно составить условие, нам нужно четко понимать, что именно хранится в базе данных, когда поле "не заполнено". Рассмотрим три состояния "пустоты":

  1. Пустая ссылка (Empty Reference): Это значение по умолчанию для ссылочных типов (Справочники, Документы). Запись физически существует, поле имеет тип Ссылка, но указывает "в никуда". Это аналог пустого значения. Именно это состояние чаще всего встречается в регистрах сведений, если реквизит не был заполнен пользователем.
  2. NULL: Это отсутствие значения как такового. В языке запросов NULL появляется, как правило, в результате соединения таблиц (левое или полное соединение), когда для записи из одной таблицы не нашлось соответствия в другой. Если вы просто читаете данные из одной таблицы (например, СрезПоследних), значение NULL там встретится вряд ли, если только само поле не является составным типом, который не был инициализирован.
  3. Неопределено (Undefined): Встречается в полях составного типа, когда тип значения еще не выбран. В обычных реквизитах справочников или регистров встречается реже, чем пустая ссылка.

Функция ЕСТЬNULL (или ISNULL) работает только с типом NULL. Она бесполезна для проверки Пустой ссылки.

Правильное решение: Проверка на пустую ссылку

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


ВЫБОР 
    КОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения = ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
    ТОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизации 
    ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения 
КОНЕЦ КАК Подразделение

В этом случае мы сравниваем Ссылку со Ссылкой. Такое условие отработает корректно.

Универсальное решение: Обработка и NULL, и Пустой ссылки

В сложных запросах, особенно где присутствуют соединения таблиц, поле может оказаться как NULL (нет записи), так и ПустойСсылкой (запись есть, но поле не заполнено). Чтобы гарантированно подставить альтернативное значение, нам нужно учесть оба варианта. Разберем наиболее надежный способ написания запроса.

Способ 1: Использование ЕСТЬNULL для приведения типов

Мы можем сначала превратить потенциальный NULL в пустую ссылку, а затем проверить результат на равенство пустой ссылке.


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

Способ 2: Явное перечисление условий

Этот способ часто более читаем и понятен при отладке:


ВЫБОР 
    КОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения ЕСТЬ NULL 
       ИЛИ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения = ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
    ТОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизации 
    ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения 
КОНЕЦ

Особенности работы с составными типами

Если поле ПодразделениеОрганизацииЗавершения имеет составной тип (может хранить ссылки на разные справочники), проверка усложняется. Сравнение с пустой ссылкой конкретного справочника может не сработать, если в поле записана пустая ссылка другого типа или значение Неопределено. В таких случаях лучше проверять "от обратного" — что значение заполнено, или использовать оператор ССЫЛКА, если нас интересует конкретный тип. Однако самый простой вариант для составных типов в запросе — проверить на Неопределено, если это допустимо логикой: ... ГДЕ Поле = ЗНАЧЕНИЕ(Неопределено) ...

Альтернатива: Вычисляемые поля в СКД

Если вы не хотите усложнять текст SQL-запроса, Система Компоновки Данных позволяет решить эту задачу на уровне настроек — через Вычисляемые поля. В языке выражений СКД (не путать с языком запросов) есть очень удобная функция ЗначениеЗаполнено(). Она универсальна: она возвращает Ложь для NULL, Неопределено, пустых ссылок, пустых строк, нуля и ложи. Вы можете создать вычисляемое поле, например ИтоговоеПодразделение, и прописать в выражении:


ВЫБОР 
    КОГДА ЗначениеЗаполнено(ПодразделениеОрганизацииЗавершения) 
    ТОГДА ПодразделениеОрганизацииЗавершения 
    ИНАЧЕ ПодразделениеОрганизации 
КОНЕЦ

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

Резюме

Подведем итог, как избежать ошибки с пустыми строками в отчетах:

  1. Никогда не сравнивайте ссылочные поля (Справочники, Документы) с кавычками "". Это сравнение всегда дает Ложь.
  2. Для проверки ссылок используйте конструкцию ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).
  3. Функция ЕСТЬNULL заменяет только технический NULL (отсутствие записи), но не заменяет пустую ссылку.
  4. В СКД используйте мощь языка выражений компоновки данных и функцию ЗначениеЗаполнено() для универсальной проверки.
← На главную