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