Разработка и Конфигурация · 12 мин
Как в запросе 1С проверить дату на пустое значение
Как в запросе 1С проверить дату на пустое значение: ДАТАВРЕМЯ(1,1,1), ЗНАЧЕНИЕ, ЕСТЬ NULL и типовые ошибки при сравнении пустых дат.
Пустая дата в 1С — это не NULL и не пустая строка, а вполне конкретное значение: начало отсчёта календаря, то есть 1 января года 1, 00:00:00. Из-за этого проверка «дата не заполнена» в запросе строится иначе, чем проверка ссылок или строк, и попытка сравнить поле с NULL или с пустой строкой результата не даст. Понимание того, как платформа хранит пустую дату, избавляет от характерных ошибок в условиях ГДЕ, ВЫБОР и при соединениях таблиц.
В языке запросов 1С есть несколько способов записать пустую дату: литерал ДАТАВРЕМЯ(1,1,1), функция ЗНАЧЕНИЕ с типом даты и передача значения через параметр. Все они равнозначны, но у каждого есть нюансы синтаксиса и сценарии, где вариант удобнее. Ниже разобраны рабочие конструкции, типичные ошибки и способы проверить результат.
Что такое пустая дата в 1С и почему это не NULL
В платформе 1С тип «Дата» не допускает отсутствия значения. Если реквизит типа «Дата» не заполнен, в нём хранится значение 01.01.0001 00:00:00 — начало календарного отсчёта. При выводе в пользовательском интерфейсе такое значение отображается как пустое, что и создаёт иллюзию «отсутствующей» даты.
NULL в запросах 1С означает другое: отсутствие записи при соединении таблиц (например, при ЛЕВОМ СОЕДИНЕНИИ, когда справа не нашлось пары) или значение, которое невозможно вычислить. Поэтому конструкция ГДЕ ДатаОплаты ЕСТЬ NULL найдёт только строки, где поле стало NULL из-за соединения, но не найдёт документы с незаполненной датой.
Из этого следует главное правило: чтобы отобрать записи с незаполненной датой, её нужно сравнить с конкретным значением 01.01.0001. Платформа предоставляет для этого встроенный литерал ДАТАВРЕМЯ(1,1,1), который и используется в подавляющем большинстве случаев.
Основной способ: сравнение с ДАТАВРЕМЯ(1,1,1)
Стандартная проверка на пустую дату выглядит как сравнение поля с литералом ДАТАВРЕМЯ(1,1,1). Функция ДАТАВРЕМЯ в языке запросов принимает числовые параметры: год, месяц, день и, при необходимости, часы, минуты, секунды. Вызов ДАТАВРЕМЯ(1,1,1) возвращает 1 января года 1, то есть ровно то значение, которое хранится в незаполненном реквизите.
ВЫБРАТЬ
РеализацияТоваров.Ссылка КАК Документ,
РеализацияТоваров.ДатаОтгрузки КАК ДатаОтгрузки
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваров
ГДЕ
РеализацияТоваров.ДатаОтгрузки = ДАТАВРЕМЯ(1, 1, 1)
Обратное условие — отбор только заполненных дат — записывается через неравенство: ГДЕ ДатаОтгрузки <> ДАТАВРЕМЯ(1,1,1). Встречается и вариант с «больше»: ГДЕ ДатаОтгрузки > ДАТАВРЕМЯ(1,1,1). Оба условия дают одинаковый результат, поскольку пустая дата — минимально возможное значение типа; любая реальная дата больше неё.
Если нужно проверить несколько дат одновременно, условия комбинируются через И и ИЛИ с обязательными скобками: ГДЕ (ДатаОтгрузки = ДАТАВРЕМЯ(1,1,1) ИЛИ ДатаОплаты = ДАТАВРЕМЯ(1,1,1)). Без скобок приоритет И над ИЛИ может изменить логику отбора.
ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1) // дата не заполнена
ГДЕ Документ.ДатаОплаты <> ДАТАВРЕМЯ(1, 1, 1) // дата заполненаПроверка в конструкции ВЫБОР и вывод признака
Часто задача не в отборе, а в том, чтобы показать в отчёте или выборке признак заполненности даты. Для этого условие помещается в конструкцию ВЫБОР, которая возвращает понятное значение вместо самой пустой даты.
ВЫБРАТЬ
Заказ.Ссылка КАК Заказ,
ВЫБОР
КОГДА Заказ.ДатаОтгрузки = ДАТАВРЕМЯ(1, 1, 1)
ТОГДА "Не запланирована"
ИНАЧЕ "Запланирована"
КОНЕЦ КАК СтатусОтгрузки
ИЗ
Документ.ЗаказПокупателя КАК Заказ
Такой приём удобен в отчётах на СКД: вместо даты 01.01.0001, которая сбивает пользователей, выводится осмысленная строка. Альтернатива — оставить дату как есть и настроить формат поля в СКД, указав строку представления пустой даты, но конструкция ВЫБОР гибче, когда статус участвует в дальнейших расчётах или группировках.
Важно не перепутать: если поле может содержать NULL (например, пришло из левого соединения), то одного сравнения с ДАТАВРЕМЯ недостаточно — NULL не равен ничему, включая пустую дату, и условие по такой строке просто не сработает. О комбинированной проверке — ниже.
Пустая дата и NULL: комбинированная проверка
Когда поле даты получено соединением таблиц, в результате могут одновременно встречаться NULL (пары не нашлось) и пустая дата (пара есть, но реквизит не заполнен). Пользователь обычно воспринимает оба случая одинаково — «даты нет», — поэтому проверять нужно оба состояния.
ВЫБРАТЬ
Заказ.Ссылка КАК Заказ,
Оплаты.ДатаОплаты КАК ДатаОплаты
ИЗ
Документ.ЗаказПокупателя КАК Заказ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Оплаты КАК Оплаты
ПО Заказ.Ссылка = Оплаты.Заказ
ГДЕ
(Оплаты.ДатаОплаты ЕСТЬ NULL
ИЛИ Оплаты.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1))
Более компактный вариант — использовать ЕСТЬNULL с подстановкой пустой даты: ГДЕ ЕСТЬNULL(Оплаты.ДатаОплаты, ДАТАВРЕМЯ(1,1,1)) = ДАТАВРЕМЯ(1,1,1). Функция заменяет NULL на пустую дату, после чего достаточно одного сравнения. Учтите, что оборачивание поля в функцию может мешать использованию индексов, поэтому на больших таблицах вариант с ИЛИ иногда работает быстрее.
Альтернативные способы: ЗНАЧЕНИЕ и параметр запроса
Второй способ записать пустую дату — функция ЗНАЧЕНИЕ с указанием типа. Для даты синтаксис менее очевиден, чем для перечислений: в языке запросов нет предопределённого значения «пустая дата», поэтому ЗНАЧЕНИЕ для дат напрямую пустое значение не вернёт. На практике для пустой даты используют именно ДАТАВРЕМЯ(1,1,1), а ЗНАЧЕНИЕ применяют для ссылочных типов.
Третий способ — передать пустую дату через параметр. Это удобно, когда условие формируется в коде и должно быть опциональным:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка КАК Документ
|ИЗ
| Документ.Отпуск КАК Док
|ГДЕ
| Док.ДатаОкончания = &ПустаяДата";
Запрос.УстановитьПараметр("ПустаяДата", Дата(1, 1, 1));
Во встроенном языке пустая дата задаётся как Дата(1,1,1) или литералом '00010101'. Передача через параметр также позволяет строить конструкции вида ГДЕ (&ПроверятьДату = ЛОЖЬ ИЛИ Док.ДатаОкончания = &ПустаяДата), включая и отключая фильтр без изменения текста запроса.
Способы задать пустую дату
Основной вариант. Простой и читаемый, работает везде, включая СКД и консоль запросов.
Подходит, когда условие формируется из кода или его нужно включать опционально. Требует установки параметра до выполнения.
Объединяет проверку NULL и пустой даты после соединений. Может замедлять запрос на больших таблицах.
Типичные ошибки при проверке пустой даты
Самая частая ошибка — сравнение даты с пустой строкой или с нулём: ГДЕ ДатаОплаты = "". Платформа либо вернёт пустой результат, либо выдаст ошибку несовместимости типов при выполнении. Дата сравнивается только с датой.
Вторая ошибка — проверка через ЕСТЬ NULL там, где соединений нет. Реквизит типа «Дата» в таблице документа не может быть NULL, поэтому такой запрос всегда вернёт пустую выборку, и причину бывает трудно заметить, особенно если запрос большой.
Третья группа ошибок связана со временем. Если реквизит имеет состав «Дата и время» и заполняется программно, в нём может оказаться, например, 01.01.0001 00:00:01 — формально не пустая дата. Проверка = ДАТАВРЕМЯ(1,1,1) такое значение не поймает. В подозрительных случаях стоит проверять диапазон: ГДЕ ДатаОплаты <= ДАТАВРЕМЯ(1,1,1,23,59,59).
Четвёртая ошибка — проверка даты в виртуальных таблицах без учёта того, что период регистра заполнен всегда. Условие на «пустой период» в регистре накопления бессмысленно: поле Период там обязательное и пустым не бывает.
Как проверить результат запроса
Надёжный способ убедиться, что условие написано правильно, — выполнить запрос в консоли запросов на тестовой базе и сравнить выборки. Сначала выполните запрос без условия и посмотрите, какие значения реально хранятся в поле: пустые даты в консоли обычно отображаются как 01.01.0001 или пустая ячейка.
Затем выполните запрос с условием = ДАТАВРЕМЯ(1,1,1) и отдельно с условием <> ДАТАВРЕМЯ(1,1,1). Сумма строк двух выборок должна совпасть с общим числом строк без условия. Если сумма меньше — в данных встречаются NULL (проверьте соединения) или значения с неожиданным временем.
Как проверить результат
В сумме дают общее число строк без условия
Сумма меньше — есть NULL или даты с временем
Пустые даты видны как 01.01.0001
Встречаются NULL — поле приходит из соединения
Отбор «равно пустой дате» фильтрует записи
Отбор ничего не находит — проверьте тип параметра
В отчётах на СКД дополнительно проверьте, что параметр отбора имеет тип «Дата» с нужным составом. Если пользователь выбирает «пустую дату» в отборе, а тип параметра задан как строка, сравнение молча перестанет работать.
Особые случаи: составные типы и динамические списки
Если реквизит имеет составной тип, включающий дату, значение может быть заполнено, но другим типом — например, строкой или числом. Тогда сравнение с ДАТАВРЕМЯ(1,1,1) для таких строк не выполнится, и они выпадут из обеих выборок. Надёжнее привести тип: ГДЕ ВЫРАЗИТЬ(Реквизит КАК ДАТА) = ДАТАВРЕМЯ(1,1,1) — выражение вернёт пустую дату для несоответствующих типов.
В динамических списках форм условие на пустую дату добавляется программно через отбор: элементу отбора присваивается вид сравнения «Равно» и значение Дата(1,1,1). При этом важно отключать использование элемента, когда фильтр не нужен, иначе список останется отфильтрованным без видимой причины.
В запросах к внешним источникам данных и при обменах учитывайте, что в других СУБД пустая дата может храниться как NULL. При сопоставлении данных из внешних таблиц с 1С комбинируйте проверки ЕСТЬ NULL и сравнение с ДАТАВРЕМЯ(1,1,1), как показано выше.
FAQ
Чем отличается ДАТАВРЕМЯ(1,1,1) от ЕСТЬ NULL?
ДАТАВРЕМЯ(1,1,1) — это конкретное значение 01.01.0001, которым заполнен незаполненный реквизит типа «Дата». ЕСТЬ NULL проверяет отсутствие значения, которое возникает при соединениях таблиц. Для обычного реквизита документа ЕСТЬ NULL никогда не выполнится.
Как проверить, что дата заполнена?
Используйте условие ГДЕ Поле <> ДАТАВРЕМЯ(1,1,1) или ГДЕ Поле > ДАТАВРЕМЯ(1,1,1). Оба варианта эквивалентны, так как пустая дата — минимально возможное значение типа.
Почему условие = ДАТАВРЕМЯ(1,1,1) не находит записи, хотя даты визуально пустые?
Чаще всего поле приходит из левого соединения и содержит NULL — добавьте проверку ЕСТЬ NULL через ИЛИ. Реже в дате с составом «Дата и время» записано ненулевое время; тогда проверяйте диапазон <= ДАТАВРЕМЯ(1,1,1,23,59,59).
Как задать пустую дату в параметре запроса из кода?
Передайте значение Дата(1,1,1) или литерал '00010101': Запрос.УстановитьПараметр("ПустаяДата", Дата(1,1,1)). В тексте запроса параметр сравнивается с полем обычным образом: ГДЕ Док.Дата = &ПустаяДата.
Как вывести в отчёте «Не указана» вместо пустой даты?
Используйте конструкцию ВЫБОР: ВЫБОР КОГДА Поле = ДАТАВРЕМЯ(1,1,1) ТОГДА "Не указана" ИНАЧЕ ... КОНЕЦ. В СКД альтернатива — настройка формата поля с представлением пустой даты.
Работает ли проверка пустой даты в запросах к регистрам?
Да, для реквизитов и измерений типа «Дата» сравнение с ДАТАВРЕМЯ(1,1,1) работает так же. Но поле Период регистра заполнено всегда, и проверять его на пустоту бессмысленно.
Что важно запомнить
Пустая дата в 1С — это значение 01.01.0001, а не NULL. Проверяйте её сравнением с ДАТАВРЕМЯ(1,1,1), добавляйте ЕСТЬ NULL при соединениях, учитывайте состав «Дата и время» и проверяйте результат, сопоставляя количество строк в выборках с условием и без.