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

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

Как в запросе 1С сравнить с пустой датой

Как в запросе 1С сравнить поле с пустой датой: ДАТАВРЕМЯ(1,1,1), ЗНАЧЕНИЕ, проверка на NULL, сравнение в СКД и динамических списках, типичные ошибки.

Проверка даты на пустое значение — одна из самых частых задач при написании запросов в 1С. Документы без срока оплаты, справочники с незаполненной датой окончания действия, регистры с необязательными измерениями — во всех этих случаях нужно отобрать записи, где дата не заполнена, и сделать это корректно.

Главная сложность в том, что «пустая дата» в 1С — это не NULL и не пустая строка, а вполне конкретное значение: 1 января года 1, то есть 01.01.0001 00:00:00. Поэтому сравнение с ним выполняется через литерал ДАТАВРЕМЯ(1,1,1) или через параметр, а попытка сравнить дату с пустой строкой или нулём приводит к ошибке или к неверному результату.

Ниже разобраны все рабочие способы сравнения с пустой датой: в обычном запросе, в СКД, в динамических списках и в коде, а также ситуации, когда вместо пустой даты в поле оказывается NULL, и типичные ошибки, из-за которых отбор «не срабатывает».

Что такое пустая дата в 1С и почему с ней путают NULL

В платформе 1С у типа «Дата» есть значение по умолчанию — 01.01.0001 00:00:00. Именно оно хранится в реквизите, если пользователь не заполнил дату. Это не отсутствие значения, а вполне определённая дата, поэтому сравнивать её нужно как дату, а не как «пустоту».

NULL — другое понятие. Он появляется в результате запроса, когда значения физически нет: например, при левом соединении таблиц, когда в присоединяемой таблице не нашлось строки, или при обращении к реквизиту через разыменование для объекта, у которого этого реквизита нет. NULL нельзя сравнить с ДАТАВРЕМЯ(1,1,1) — такое сравнение вернёт «ложь», даже если логически дата «не заполнена».

Практический вывод: перед написанием условия определите, откуда берётся поле. Если это реквизит одной таблицы — там будет пустая дата. Если поле приходит из соединения или через точку из другого объекта — возможен NULL, и одного сравнения с ДАТАВРЕМЯ(1,1,1) недостаточно.

Основной способ: литерал ДАТАВРЕМЯ(1,1,1)

Стандартный и самый читаемый вариант — сравнить поле напрямую с литералом пустой даты. Литерал даты в языке запросов записывается как ДАТАВРЕМЯ(Год, Месяц, День) или с временем: ДАТАВРЕМЯ(Год, Месяц, День, Час, Минута, Секунда).

ВЫБРАТЬ

РеализацияТоваров.Ссылка КАК Документ,

РеализацияТоваров.ДатаОплаты КАК ДатаОплаты

ИЗ

Документ.РеализацияТоваровУслуг КАК РеализацияТоваров

ГДЕ

РеализацияТоваров.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)

Такой запрос выберет все документы, у которых дата оплаты не заполнена. Обратное условие — документы с заполненной датой — записывается через неравенство: РеализацияТоваров.ДатаОплаты <> ДАТАВРЕМЯ(1, 1, 1) или НЕ РеализацияТоваров.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1).

Литерал можно использовать не только в секции ГДЕ, но и в ВЫБОР, в условиях соединений и в итогах. Например, вычисляемое поле-флаг: ВЫБОР КОГДА ДатаОплаты = ДАТАВРЕМЯ(1,1,1) ТОГДА "Не указана" ИНАЧЕ "Указана" КОНЕЦ.

Сравнение через параметр запроса

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Док.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Док

|ГДЕ

| Док.ДатаОплаты = &ПустаяДата";

Запрос.УстановитьПараметр("ПустаяДата", '00010101');

Значение параметра задаётся литералом даты встроенного языка: '00010101' — это и есть пустая дата. Можно также использовать Дата(1,1,1) или просто неинициализированную переменную типа Дата, хотя явный литерал надёжнее и понятнее при чтении кода.

Если параметр не установить вовсе, запрос завершится ошибкой. Если передать в параметр значение другого типа — строку или число — сравнение даст непредсказуемый результат или ошибку несоответствия типов, поэтому тип параметра стоит контролировать явно.

bsl
Запрос.УстановитьПараметр("ПустаяДата", '00010101'); // 01.01.0001 00:00:00

Проверка заполненности: комбинация с ЕСТЬ NULL

Когда поле может содержать NULL, корректная проверка «дата не заполнена» выглядит как объединение двух условий. Типичный случай — левое соединение с таблицей, где дата может отсутствовать.

ВЫБРАТЬ

Заказы.Ссылка КАК Заказ,

Оплаты.ДатаОплаты КАК ДатаОплаты

ИЗ

Документ.ЗаказПокупателя КАК Заказы

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

ПО Заказы.Ссылка = Оплаты.Заказ

ГДЕ

(Оплаты.ДатаОплаты ЕСТЬ NULL

ИЛИ Оплаты.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1))

Такое условие отберёт и заказы без записи об оплате (NULL), и заказы, где запись есть, но дата в ней не заполнена. Если оставить только сравнение с ДАТАВРЕМЯ(1,1,1), строки с NULL просто выпадут из результата, потому что любое сравнение с NULL даёт «ложь».

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

Способы проверки на пустую дату

= ДАТАВРЕМЯ(1,1,1)

Простое и быстрое сравнение. Подходит, когда поле гарантированно не содержит NULL.

Параметр запроса

Удобно при динамическом построении запроса и повторном использовании значения. Требует контроля типа параметра.

ЕСТЬ NULL ИЛИ = ДАТАВРЕМЯ(1,1,1)

Нужен при соединениях и разыменовании, где возможен NULL. Покрывает оба случая «незаполненности».

ЕСТЬNULL(Поле, ДАТАВРЕМЯ(1,1,1))

Компактная запись для полей с NULL, но функция в условии может замедлить запрос на больших таблицах.

Пустая дата в СКД и динамических списках

В схеме компоновки данных тот же литерал ДАТАВРЕМЯ(1,1,1) работает в тексте запроса набора данных. Но в отборах СКД, которые пользователь настраивает в режиме предприятия, литерал написать нельзя — там сравнение выполняется со значением, которое подставляется через параметр или выбирается из поля.

Для отбора «дата не заполнена» в СКД есть два практических приёма. Первый — добавить в запрос вычисляемое поле-флаг (например, «ДатаНеЗаполнена» со значением Истина/Ложь) и фильтровать уже по нему. Второй — в отборе использовать вид сравнения «Равно» и в качестве значения указать дату 01.01.0001; многие типовые конфигурации позволяют ввести такую дату в поле отбора вручную.

В динамических списках с произвольным запросом условие с ДАТАВРЕМЯ(1,1,1) прописывается прямо в тексте запроса списка. Если отбор должен включаться пользователем, лучше оформить его через параметр и элемент отбора формы, а не зашивать условие в запрос постоянно.

В отчётах на СКД удобнее всего добавить в запрос поле ВЫБОР КОГДА Дата = ДАТАВРЕМЯ(1,1,1) ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ и вынести его в отборы. Пользователь получает понятный флажок, а запрос остаётся простым и быстрым.
ПЗ
Практическое замечание

Сравнение в коде вне запроса

Если проверка нужна не в запросе, а во встроенном языке, используется функция ЗначениеЗаполнено() или прямое сравнение с пустой датой. Функция ЗначениеЗаполнено(ДатаОплаты) вернёт Ложь для пустой даты и Истина для любой заполненной.

Прямое сравнение выглядит так: Если ДатаОплаты = '00010101' Тогда .... Оба варианта корректны; ЗначениеЗаполнено универсальнее, потому что одинаково работает с датами, строками, ссылками и числами, и её удобно использовать, когда тип реквизита может меняться.

Важно не путать проверку в коде с проверкой в запросе: в языке запросов функции ЗначениеЗаполнено нет, там только сравнение с литералом или параметром. Попытка вставить ЗначениеЗаполнено в текст запроса приведёт к синтаксической ошибке.

Как добавить проверку на пустую дату
  1. 1
    Определите, откуда берётся поле: реквизит одной таблицы или результат соединения/разыменования.
  2. 2
    Если NULL невозможен — напишите условие Поле = ДАТАВРЕМЯ(1,1,1) в секции ГДЕ.
  3. 3
    Если NULL возможен — добавьте условие Поле ЕСТЬ NULL через ИЛИ или оберните поле в ЕСТЬNULL.
  4. 4
    Выполните запрос в консоли запросов и убедитесь, что в результат попали записи и с пустой датой, и (при необходимости) с NULL.
  5. 5
    Проверьте обратное условие (&lt;&gt; ДАТАВРЕМЯ(1,1,1)), чтобы убедиться, что заполненные даты фильтруются симметрично.

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

Самая распространённая ошибка — сравнение даты с пустой строкой или нулём: ГДЕ ДатаОплаты = "". Запрос либо упадёт с ошибкой несоответствия типов, либо молча вернёт пустой результат, потому что дата никогда не равна строке. Правильный операнд — только дата.

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

Третий нюанс — составной тип реквизита. Если поле имеет тип «Дата и строка» или подобный, сравнение с ДАТАВРЕМЯ(1,1,1) отработает только для значений-дат; пустая строка в таком поле пустой дате не равна. В этом случае условие нужно дополнять проверкой на пустую строку или на неопределённое значение.

Типичные ошибки
01
Сравнение даты с пустой строкой или нулём — ошибка типов или пустой результат; используйте ДАТАВРЕМЯ(1,1,1).
02
Игнорирование NULL при левом соединении — часть записей без даты выпадает из результата.
03
Использование ЗначениеЗаполнено в тексте запроса — функции нет в языке запросов, будет синтаксическая ошибка.
04
Передача в параметр строки "01.01.0001" вместо даты '00010101' — сравнение не сработает из-за несовпадения типов.

Наконец, помните о границе между «пустой датой» и реальной датой 01.01.0001. Если в данных по какой-то причине легально встречается дата 1 января года 1 (например, загружена из внешней системы как техническая), отличить её от незаполненной средствами запроса невозможно — значения идентичны. В таких случаях признак заполненности нужно хранить отдельно.

Итог

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

Пустая дата — это 01.01.0001 00:00:00, и в запросе она сравнивается через ДАТАВРЕМЯ(1,1,1) или параметр со значением '00010101'. При соединениях и разыменовании добавляйте проверку ЕСТЬ NULL. В коде вне запроса используйте ЗначениеЗаполнено(). Никогда не сравнивайте дату со строкой или числом.

Частые вопросы

Чем отличается пустая дата от NULL в запросе 1С?

Пустая дата — конкретное значение 01.01.0001 00:00:00, хранящееся в незаполненном реквизите типа «Дата». NULL означает отсутствие значения и появляется при соединениях таблиц или разыменовании. Сравнение с ДАТАВРЕМЯ(1,1,1) находит только пустую дату; для NULL нужна отдельная проверка ЕСТЬ NULL.

Как выбрать документы, у которых дата заполнена?

Используйте обратное условие: ГДЕ Документ.ДатаОплаты <> ДАТАВРЕМЯ(1,1,1). Если поле может содержать NULL и такие строки тоже нужно исключить, добавьте условие И НЕ Поле ЕСТЬ NULL — хотя при соединении NULL-строки и так не пройдут проверку на неравенство, поэтому дополнительное условие обычно не требуется.

Можно ли использовать ДАТАВРЕМЯ(1,1,1) в отборе динамического списка?

В тексте произвольного запроса динамического списка — да, литерал работает так же, как в обычном запросе. В пользовательском отборе списка литерал ввести нельзя; там либо указывают дату 01.01.0001 как значение отбора, либо добавляют в запрос вычисляемое поле-флаг заполненности и фильтруют по нему.

Почему условие = ДАТАВРЕМЯ(1,1,1) не находит записи, хотя даты точно пустые?

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

Как в запросе заменить пустую дату на понятный текст для отчёта?

Через конструкцию ВЫБОР: ВЫБОР КОГДА ДатаОплаты = ДАТАВРЕМЯ(1,1,1) ТОГДА "Не указана" ИНАЧЕ ПОДСТРОКА(...) КОНЕЦ — либо проще: выводите саму дату, а представление пустого значения настраивайте в СКД на закладке «Наборы данных» через оформление поля. Так отчёт останется сортировкой по настоящей дате, а не по строке.

Работает ли сравнение с пустой датой в запросах к движениям документов и регистрам?

Да, для реквизитов и измерений регистров типа «Дата» сравнение с ДАТАВРЕМЯ(1,1,1) работает так же, как для документов. Исключение — поля виртуальных таблиц и соединений, где возможен NULL: там добавляйте проверку ЕСТЬ NULL или функцию ЕСТЬNULL.