При разработке запросов в 1С:Предприятие 8 начинающие программисты часто сталкиваются с ситуацией, когда документ с определенной датой точно существует в базе, но запрос по условию Дата = &Дата его не находит. Разберем, почему так происходит, и проанализируем наиболее эффективные способы решения этой задачи, учитывая производительность системы.
В системе 1С тип данных Дата всегда содержит и календарную дату, и время (часы, минуты, секунды). Если вы вводите дату в поле поиска (например, "01.09.2023"), система по умолчанию подставляет время 00:00:00. В то же время реальные документы в базе данных записываются с конкретным временем (например, "01.09.2023 14:30:15").
При использовании оператора "равно" (=) СУБД ищет полное совпадение. Следовательно, документ, созданный в середине дня, не будет равен дате с нулевым временем. Наша задача — научить запрос игнорировать время и искать все документы внутри заданных суток.
Самый простой и правильный с точки зрения производительности способ — это поиск документов в интервале от начала нужного дня до его конца. Рассмотрим пример кода, который решает проблему:
Процедура КнопкаВыполнитьНажатие(Кнопка)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка,
| РеализацияТоваровУслуг.Дата,
| РеализацияТоваровУслуг.Контрагент,
| РеализацияТоваровУслуг.СуммаДокумента
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &ДатаНачала И &ДатаКонца";
// Используем встроенные функции для получения границ дня
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаПоиска));
Запрос.УстановитьПараметр("ДатаКонца", КонецДня(ДатаПоиска));
РезультатЗапроса = Запрос.Выполнить();
ЭлементыФормы.ТабличноеПоле1.Значение = РезультатЗапроса.Выгрузить();
ЭлементыФормы.ТабличноеПоле1.СоздатьКолонки();
КонецПроцедуры
В данном примере мы передаем в запрос две точки во времени. Функция НачалоДня() устанавливает время в 00:00:00, а КонецДня() — в 23:59:59. Это гарантирует, что все документы, созданные в течение этих суток, попадут в выборку.
Проанализируем ситуацию, которая часто встречается в советах на форумах: использование функций прямо внутри текста запроса. Рассмотрим пример, как делать не рекомендуется:
// ПЛОХОЙ ПРИМЕР (НИЗКАЯ СКОРОСТЬ)
|ГДЕ
| НАЧАЛОПЕРИОДА(РеализацияТоваровУслуг.Дата, ДЕНЬ) = &ДатаПоиска
Выясним причину, почему это плохо: Если мы применяем функцию НАЧАЛОПЕРИОДА к полю Дата в левой части условия, СУБД не сможет использовать индекс по этому полю. Системе придется прочитать каждую запись в таблице, вычислить для нее начало дня и только потом сравнить. На больших базах это приведет к значительным задержкам. Использование оператора МЕЖДУ (или сравнения через больше/меньше) позволяет СУБД выполнить поиск по индексу (Index Seek), что в десятки раз быстрее.
Существует еще более строгий подход, который исключает любые проблемы с точностью до секунды. Мы можем искать документы, которые больше или равны началу искомого дня, но строго меньше начала следующего дня.
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ Док.Дата >= &НачалоДня И Док.Дата < &НачалоСледующегоДня";
Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ДатаПоиска));
// Добавляем 1 день (86400 секунд) и берем его начало
Запрос.УстановитьПараметр("НачалоСледующегоДня", НачалоДня(ДатаПоиска + 86400));
Этот метод считается максимально корректным, так как он покрывает абсолютно весь временной диапазон суток, включая возможные микросекунды, если данные были загружены из внешних систем напрямую в SQL.
Иногда программисты пытаются использовать объект Граница для поиска документов. Важно помнить: объект Граница предназначен для работы с параметрами виртуальных таблиц (например, остатками и оборотами в регистрах). При попытке передать его в обычное условие ГДЕ для физической таблицы документов, запрос выдаст ошибку. Для документов всегда используйте стандартный тип Дата.
Подводя итог нашему разбору, выделим основные правила поиска по дате:
Дата = &Дата, если не уверены, что время документа всегда равно 00:00:00.МЕЖДУ или связку >= и <=.НачалоДня() и КонецДня() на языке 1С, а не в самом запросе.НАЧАЛОПЕРИОДА) над полями таблиц в условиях запроса для сохранения высокой скорости работы.Рассмотренные методы позволят вам создавать надежные и быстрые механизмы поиска документов в любых конфигурациях на платформе 1С:Предприятие 8.