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