При разработке отчетов и обработок в 1С разработчики часто сталкиваются с ситуацией, когда функция ЕСТЬNULL, помещенная внутрь блока ВЫБОР КОГДА ... ТОГДА, не возвращает ожидаемую строку-заглушку или значение по умолчанию. Разберем механизм возникновения этой ошибки и рассмотрим правильные варианты построения запроса.
Рассмотрим типичный пример ошибочной логики, когда к основной таблице (например, справочнику номенклатуры) присоединяется срез последних цен левым соединением:
ВЫБОР
КОГДА ЦеныНоменклатурыСрезПоследних.ВидЦены = &ВидЦены2
ТОГДА ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, "*****")
КОНЕЦ
В этом выражении кроется фундаментальная ошибка логики выполнения запросов при наличии ЛЕВОЕ СОЕДИНЕНИЕ:
ЦеныНоменклатурыСрезПоследних (включая ВидЦены и Цена) принимают значение NULL.ЦеныНоменклатурыСрезПоследних.ВидЦены = &ВидЦены2 происходит сравнение NULL = &ВидЦены2. По правилам трехзначной логики SQL результат такого сравнения не является истинным (он равен Неизвестно / False).КОГДА не выполнилось, вложенная ветка ТОГДА вообще не вычисляется. Соответственно, функция ЕСТЬNULL для цены даже не начинает выполняться.ИНАЧЕ в выражении отсутствует, вся конструкция ВЫБОР возвращает NULL, и колонка отчета остается пустой вместо ожидаемого текста.Цена уже содержит числовое значение, и ЕСТЬNULL просто возвращает саму цену, никогда не доходя до значения по умолчанию.Также важно помнить, что функция ЕСТЬNULL реагирует исключительно на специальное значение NULL. Если в регистре записана явная нулевая цена (0) или пустая строка, функция ЕСТЬNULL не заменит их, так как эти значения имеют конкретный тип и не являются отсутствующими записями.
Если требуется вывести определенную заглушку при невыполнении условия, необходимо явно определить ветку ИНАЧЕ:
ВЫБОР
КОГДА ЦеныНоменклатурыСрезПоследних.ВидЦены = &ВидЦены2
ТОГДА ЦеныНоменклатурыСрезПоследних.Цена
ИНАЧЕ "*****"
КОНЕЦ
В данном случае, если запись с нужным видом цены отсутствует (поле ВидЦены равно NULL), условие не выполнится, и запрос вернет значение из ветки ИНАЧЕ.
Наиболее производительный и архитектурно правильный подход в платформе 1С — фильтровать данные среза на уровне параметров виртуальной таблицы. Разберем по шагам:
РегистрСведений.ЦеныНоменклатуры.СрезПоследних.ЛЕВОЕ СОЕДИНЕНИЕ.ЕСТЬNULL напрямую к полю цены, без использования громоздких конструкций ВЫБОР.Посмотрим на пример текста запроса:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Номенклатура,
ЕСТЬNULL(Цены.Цена, 0) КАК Цена
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЦены) КАК Цены
ПО СпрНоменклатура.Ссылка = Цены.Номенклатура
Если по каким-либо причинам параметры виртуальной таблицы не используются, условие отбора по виду цены следует выносить в секцию связи таблиц:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
ПО СпрНоменклатура.Ссылка = Цены.Номенклатура
И Цены.ВидЦены = &ВидЦены
Вывод строк вида "*****" в одном поле с числовыми значениями цен приводит к созданию составного типа данных. Это может вызвать проблемы при расчете итогов, сортировке и выгрузке данных в типизированные структуры.
Если цель — визуально выделить отсутствие цены в отчете, правильнее оставить поле числовым, возвращая 0 при NULL, а визуальное представление настроить через Условное оформление схемы компоновки данных:
ЕСТЬNULL(Цены.Цена, 0) КАК Цена.Цена.Цена Равно 0 (или Цена Не заполнено).*****.Такой подход сохраняет корректную типизацию данных в запросе и обеспечивает требуемое визуальное отображение для пользователя.