Работа с временными интервалами и конкретными моментами времени является одной из самых частых задач при разработке на платформе 1С:Предприятие 8. Правильное формирование условия отбора в запросе напрямую влияет на производительность системы и корректность получаемых отчетов. Ошибки в синтаксисе или непонимание принципов работы типа ДатаВремя часто приводят к тому, что выборка оказывается пустой или, наоборот, содержит лишние записи.

В этой статье мы детально разберем, как корректно задавать даты в тексте запроса, как использовать параметры и какие нюансы следует учитывать при сравнении временных меток. Мы рассмотрим как статические значения, так и динамические вычисления, необходимые для построения гибких отчетов.

Понимание того, как платформа обрабатывает дату в условиях ГДЕ, позволит вам избежать распространенных ловушек, связанных с точностью до секунды или миллисекунды. Это особенно критично при работе с журналами документов и регистрами накопления.

Синтаксис literal-констант в запросах 1С

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

Базовый формат записи выглядит следующим образом: 'ГГГГ-ММ-ДД ЧЧ:ММ:СС'. Обратите внимание, что разделение элементов даты и времени производится дефисами и двоеточиями, а между датой и временем обязательно должен стоять пробел. Отсутствие времени также допустимо, но в этом случае оно будет считаться равным нулю.

Рассмотрим конкретный пример выборки документов за определенное число. В данном случае мы используем жестко заданное значение внутри строки запроса:

ВЫБРАТЬ

РеализацияТоваровУслуг.Ссылка КАК Ссылка,

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

ИЗ

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

ГДЕ

РеализацияТоваровУслуг.Дата МЕЖДУ '2023-10-01 00:00:00' И '2023-10-01 23:59:59'

Использование литералов удобно для отладки, но в реальном коде их применяют редко, так как они делают запрос негибким. Для динамической работы необходимо использовать параметры или функции языка запросов.

💡

Всегда указывайте время явно, даже если вам нужна только дата. Значение '2023-10-01' автоматически превратится в '2023-10-01 00:00:00', что может привести к потере документов, проведенных в течение дня.

Использование параметров запроса для работы с датами

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

Параметр в тексте запроса обозначается знаком & перед именем. При выполнении запроса через объект Запрос в коде на встроенном языке, вы должны заполнить значения этих параметров перед вызовом метода Выполнить(). Тип передаваемого значения должен соответствовать типу поля в базе данных, то есть быть ДатаВремя.

Пример корректной передачи параметра из кода 1С:

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

Запрос.Текст = "ВЫБРАТЬ.. ГДЕ Дата МЕЖДУ &Начало И &Конец";

Запрос.УстановитьПараметр("Начало", НачалоДня(ДатаНачала));

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

Результат = Запрос.Выполнить();

Особое внимание стоит уделить границам интервала.

  • 📅 Используйте функцию НачалоДня() для левой границы интервала, чтобы захватить все события с 00:00:00.
  • ⏰ Для правой границы применяйте КонецДня(), если вам нужно включить весь выбранный день полностью.
  • ⚠️ Будьте осторожны с функцией ТекущаяДата() — она содержит точное время до секунды, что может обрезать выборку.
📊 Как вы чаще всего передаете даты в запрос?
Через параметры (&Дата)
Хардкодом в тексте ('2023..')
Через временные таблицы
Через соединения

Особенности сравнения дат и временных интервалов

При фильтрации данных по дате разработчики часто сталкиваются с проблемой "потерянных" документов. Это происходит из-за того, что тип ДатаВремя в 1С хранит информацию с точностью до секунды (а внутренне и до более мелких долей). Операторы сравнения работают строго по математическим правилам.

Если вы напишете условие ГДЕ Дата = '2023-10-05', система будет искать документы, проведенные ровно в 00:00:00 этого дня. Все документы, созданные в 10:15 или 14:30, не попадут в выборку, так как они не равны началу суток. Для выбора диапазона всегда используйте оператор МЕЖДУ или комбинацию >= и <=.

⚠️ Внимание: Оператор МЕЖДУ включает граничные значения. Условие МЕЖДУ '2023-10-01' И '2023-10-01' вернет только записи за 00:00:00. Чтобы получить весь день, верхняя граница должна быть '2023-10-01 23:59:59' или использоваться функция КонецДня().

Еще один важный аспект — сравнение даты с пустым значением. В 1С дата может быть неопределенной. Для проверки на заполненность используется конструкция ЕСТЬNULL() или сравнение с неопределенным значением, однако в запросах чаще проверяют конкретные диапазоны.

При работе с большими массивами данных неправильное использование индексов по дате может привести к полному сканированию таблицы. Убедитесь, что условие по дате является сущностным для выбора и не содержит лишних преобразований в теле условия.

💡

Всегда расширяйте диапазон выборки до конца дня (23:59:59), если пользователь выбрал конкретную дату в интерфейсе, иначе документы второй половины дня будут потеряны.

Функции работы с датами внутри языка запросов

Язык запросов 1С предоставляет богатый набор встроенных функций для манипуляции датами непосредственно на стороне СУБД. Использование этих функций позволяет сократить объем передаваемых данных и упростить логику приложения, переложив вычисления на сервер баз данных.

Одной из самых полезных функций является НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА. Они позволяют динамически вычислять границы месяцев, кварталов или лет без участия кода на клиенте. Это особенно полезно при формировании регламентных отчетов.

Таблица основных функций для работы с временными метками в запросе:

Функция Описание Пример использования
НАЧАЛОДНЯ(Дата) Обрезает время до 00:00:00 НАЧАЛОДНЯ(&Дата)
КОНЕЦДНЯ(Дата) Устанавливает время 23:59:59 КОНЕЦДНЯ(&Дата)
НАЧАЛОМЕСЯЦА(Дата) Первый день текущего месяца НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА())
ДОБАВИТЬКДАТЕ(Дата, Интервал) Сдвиг даты на интервал ДОБАВИТЬКДАТЕ(&Дата, 1, МЕСЯЦ)

Использование функции РАЗНОСТЬДАТ позволяет вычислять количество дней, месяцев или лет между двумя датами прямо в выборке. Это удобно для расчетов возраста документов или сроков оплаты.

Нюанс функции ДОБАВИТЬКДАТЕ

При добавлении месяцев к дате 31 января результат может быть 28 февраля (или 29 в високосный год), так как 31 февраля не существует. Система автоматически корректирует дату на последний день месяца.

Типичные ошибки и способы их устранения

Даже опытные разработчики допускают ошибки при работе с временными данными. Чаще всего проблемы связаны с несовпадением часовых поясов (если используется территориально распределенная база) или неверным пониманием того, как хранится дата в таблице SQL.

Частая ошибка — попытка сравнить дату с строкой без явного приведения типов в некоторых специфических конфигурациях или при использовании динамического списка. Хотя язык запросов 1С обычно сам справляется с приведением, явное указание типа в параметрах надежнее.

  • Ошибка: Использование ГОД(Дата) = 2023 в условии WHERE. Это запрещает использование индекса по дате и вызывает полное сканирование таблицы.
  • Решение: Используйте диапазон МЕЖДУ '2023-01-01' И '2023-12-31 23:59:59' для сохранения производительности.
  • Ошибка: Сравнение даты документа с датой сеанса без учета времени, что приводит к пустой выборке в течение дня.

Также стоит упомянуть проблему "вечных" дат. В 1С существует максимальное значение даты (год 9999). При фильтрации открытых периодов иногда используют конструкцию ИСТИНА или сравнение с этой максимальной датой, что может быть неочевидно для читающего код.

⚠️ Внимание: Никогда не используйте преобразование даты в строку (СТРОКА(Дата)) внутри условия отбора ГДЕ. Это гарантированно отключит индексацию и замедлит работу базы в разы при росте объема данных.

☑️ Проверка производительности запроса с датами

Выполнено: 0 / 4

Оптимизация запросов с датами для больших баз

Когда объем данных в информационной базе исчисляется миллионами записей, подход к написанию запросов с датами становится критическим фактором производительности. Сервер 1С и СУБД (MS SQL, PostgreSQL) должны иметь возможность эффективно использовать индексы по полям даты.

Главное правило оптимизации: поле, по которому ведется индексация (в нашем случае Дата), должно стоять в условии в "чистом" виде, без обертывания в функции. Левая часть оператора сравнения должна содержать имя поля таблицы.

Неправильно: ГДЕ ГОД(Реестр.Дата) = 2023. В этом случае СУБД вынуждена вычислить год для каждой строки таблицы, что убивает производительность.

Правильно: ГДЕ Реестр.Дата МЕЖДУ '2023-01-01' И '2023-12-31 23:59:59'. Здесь движок базы данных может сразу перейти к нужному участку индекса.

Кроме того, при работе с виртуальными таблицами регистров накопления (например, РегистрНакопления.ОстаткиТоваров.Остатки) важно правильно указывать срез. Условие по дате в виртуальной таблице часто передается как параметр виртаблицы, а не в секции ГДЕ.

ВЫБРАТЬ

Остатки.Номенклатура,

Остатки.КоличествоОстаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(,&Дата) КАК Остатки

Такой синтаксис гарантирует, что система воспользуется оптимальным алгоритмом получения среза на момент времени, заранее рассчитанным разработчиками платформы.

💡

Для высокой производительности всегда передавайте дату среза в параметры виртуальной таблицы регистра, а не фильтруйте результат оператором ГДЕ после выборки.

Как правильно написать дату в запросе 1С без времени?

Если вы укажете дату в формате '2023-10-05', система автоматически дополнит её временем 00:00:00. Чтобы выбрать весь день, необходимо явно указать конец дня: '2023-10-05 23:59:59' или использовать функцию КОНЕЦДНЯ('2023-10-05').

Почему запрос не находит документы за сегодня?

Скорее всего, вы используете условие равенства Дата = &ТекущаяДата. Так как ТекущаяДата() содержит точное время (например, 14:35:10), а документы могут быть проведены в 10:00:00, они не совпадут. Используйте диапазон от НачалоДня() до КонецДня().

Можно ли использовать русские названия месяцев в запросе?

Нет, в тексте запроса 1С даты должны указываться строго в числовом формате ГГГГ-ММ-ДД. Написание вроде '05 октября 2023' вызовет ошибку синтаксиса. Преобразование строки в дату возможно только через функции встроенного языка перед передачей в запрос.

Что делать, если дата хранится в строковом поле?

Хранить дату в строке — архитектурная ошибка. Если это неизбежно, используйте функцию СТРОКАВДАТУ() в условии, но помните, что это отключит индексы. Лучше привести данные к типу ДатаВремя средствами миграции или вычисляемым полем.