Работа с выборками данных в системе 1С Предприятие невозможна без использования временных интервалов. Каждая система учета — будь то бухгалтерия, склад или производство — оперирует временем как ключевым измерением. Правильная организация выборки за конкретный отрезок времени критически влияет на производительность базы данных и точность получаемой отчетности.
Часто начинающие разработчики совершают ошибку, пытаясь получить просто конкретную дату или игнорируя особенности работы с интервалами. Это приводит к тому, что в отчет попадают лишние записи или, наоборот, недостаёт необходимых документов, которые были проведены в граничные моменты времени. Фильтрация по периоду требует особого внимания к типу данных и логике построения запроса.
В этой статье мы разберем все существующие способы задания временных рамок. От простейшей подстановки параметров до использования специальных объектов метаданных, которые упрощают жизнь программисту.
Базовый подход с использованием параметров запроса
Самый распространенный и рекомендуемый способ фильтрации данных — это передача значений начала и конца периода в виде параметров запроса. Такой подход позволяет движку 1С оптимизировать план выполнения и эффективно использовать индексы базы данных.
Для реализации этого метода в тексте запроса необходимо указать идентификаторы параметров, начинающиеся со знака "&". Например, вы можете использовать конструкцию &НачалоПериода и &КонецПериода. В коде на встроенном языке эти параметры заполняются перед выполнением запроса через объект Запрос.УстановитьПараметр.
Важно отметить, что тип значения параметра должен строго соответствовать типу поля в таблице базы данных. Если поле "Дата" имеет тип ДатаВремя, то и параметр должен содержать время. Иначе может возникнуть неявное преобразование типов, которое иногда влияет на скорость работы.
- 🚀 Передача параметров напрямую в текст запроса обеспечивает максимальную читаемость кода.
- 🛡 Использование параметров защищает от SQL-инъекций и ошибок синтаксиса.
- ⚙ Гибкость настройки: вы можете легко менять диапазон без переписывания логики выборки.
Рассмотрим пример стандартной конструкции. Мы хотим выбрать все документы реализации за январь. В этом случае мы передаем в параметр начала 01.01.2026 00:00:00, а в параметр конца — 31.01.2026 23:59:59.
Запрос = Новый Запрос("ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода");
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));
Используйте встроенные функции НачалоМесяца() и КонецМесяца() для автоматического расчета границ, чтобы избежать ошибок ручного ввода дат.
Оператор МЕЖДУ и его особенности в 1С
Оператор МЕЖДУ (или BETWEEN в терминах SQL) является основным инструментом для задания диапазона. Однако в 1С он работает инклюзивно, то есть включает в выборку значения, равные нижней и верхней границе. Это свойство нужно учитывать при работе с типом данных "ДатаВремя".
Если вы укажете конец периода как 31.01.2026 без времени, система интерпретирует это как 31.01.2026 00:00:00. В результате все документы, проведенные 31 января после полуночи, будут отсечены. Это классическая ошибка, из-за которой отчеты "не сходятся" на копейку или на несколько документов.
Чтобы избежать потери данных, всегда явно указывайте время конца периода. Лучшей практикой считается использование функции КонецДня, КонецМесяца или добавление одной секунды к началу следующего периода. Точность временной метки определяет полноту вашей выборки.
Оператор МЕЖДУ включает граничные значения. Если поле имеет тип ДатаВремя, обязательно указывайте время 23:59:59 для конца дня, иначе данные за этот день могут быть потеряны.
Альтернативный подход — использование строгого неравенства для верхней границы. Вместо МЕЖДУ Начало И Конец можно писать >= Начало И < КонецСледующегоПериода. Этот метод часто используется при работе с регистрами накопления, где важно четко разграничить срезы.
⚠️ Внимание: При использовании оператора
МЕЖДУс типом "Дата" (без времени) система может неявно добавлять время. Всегда проверяйте тип поля в конфигураторе: если там "ДатаВремя", передавайте полное значение с временем.
Использование объекта ГраницаПериода
Для упрощения работы с периодами в платформе 1С существует специальный объект метаданных — ГраницаПериода. Он позволяет не задумываться о том, включать ли граничную точку в выборку или нет. Этот объект явно указывает системе, как обрабатывать края интервала.
Объект ГраницаПериода имеет два свойства: само значение даты/времени и вид границы (Включать или Не включать). Это особенно полезно при формировании отчетов, где пользователь может выбрать опцию "Включать конец периода" в интерфейсе.
При передаче такого объекта в параметр запроса, 1С автоматически корректирует условие выборки. Вам не нужно вручную добавлять секунды или вычитать их. Это делает код более устойчивым к изменениям и понятным для других разработчиков.
Граница = Новый ГраницаПериода(КонецМесяца(Дата), ВидГраницыПериода.Включать);
Запрос.УстановитьПараметр("КонецПериода", Граница);
Технические детали работы ГраницыПериода
Внутри движка запросов этот объект преобразуется в соответствующее неравенство. Если выбрано "Включать", для типа ДатаВремя время устанавливается в максимально возможное значение для данной даты (23:59:59). Если "Не включать" — в начало следующего интервала.
Использование этого подхода рекомендуется в типовых конфигурациях и при разработке сложных аналитических отчетов. Это стандарт де-факто для профессиональной разработки на платформе 8.3 и выше.
Работа с регистрами накопления и виртуальными таблицами
При выборке данных из регистров накопления ситуация усложняется наличием виртуальных таблиц, таких как Остатки и Обороты. Эти таблицы уже содержат логику работы с периодами внутри себя, и неправильное указание параметров может привести к некорректным остаткам.
Виртуальная таблица Остатки требует указания периода, на который рассчитываются остатки. Параметры передаются в скобках после имени таблицы. Здесь также важно соблюдать правила инклюзивности границ.
| Виртуальная таблица | Необходимые параметры | Особенность указания периода |
|---|---|---|
| Остатки | Период | Момент времени, на который считаем остаток (срез последних движений). |
| Обороты | НачалоПериода, КонецПериода | Интервал, за который суммируются приходы и расходы. |
| ОборотыДс | НачалоПериода, КонецПериода | Аналогично таблице Обороты, но для денежных средств. |
Например, чтобы получить обороты за месяц, вы должны передать в параметры виртуальной таблицы начало и конец месяца. Ошибка в одном дне приведет к тому, что документы последнего дня месяца не попадут в отчет об оборотах, но могут попасть в остаток на конец периода, если логика не согласована.
При работе с виртуальными таблицами помните, что параметры периода часто являются обязательными. Если их не передать, запрос может выдать ошибку выполнения или вернуть пустой результат, в зависимости от версии платформы и настроек конфигурации.
Специфика работы с типами Дата и ДатаВремя
Одной из самых коварных проблем при указании периода является несоответствие типов данных. В старых конфигурациях или отдельных справочниках поле даты может иметь тип просто Дата, в то время как в документах обычно используется ДатаВремя.
Если вы сравниваете поле типа Дата (где время всегда 00:00:00) с параметром, содержащим время 15:30:00, условие равенства никогда не выполнится. При использовании оператора МЕЖДУ это может сработать, но только если границы подобраны идеально.
Для приведения типов можно использовать функцию НАЧАЛОДНЯ() прямо в тексте запроса. Это позволит отсечь время у поля базы данных и сравнивать только календарные дни. Однако учтите, что применение функций к полям в условии ГДЕ может отключить использование индексов и замедлить запрос на больших объемах данных.
⚠️ Внимание: Избегайте применения функций к полям таблицы в условии WHERE (например,
НАЧАЛОДНЯ(Таблица.Дата)), если таблица содержит миллионы записей. Это приводит к полному сканированию таблицы (Full Scan) вместо поиска по индексу.
Лучшим решением является приведение типа на стороне параметра перед установкой его в запрос. Если поле в базе — Дата, то и параметр &НачалоПериода должен быть очищен от времени с помощью функции НачалоДня в коде 1С.
Динамическое формирование периода в коде
Часто период выборки не задается пользователем жестко, а вычисляется динамически. Например, "Текущий месяц", "Предыдущий квартал" или "С начала года". Для таких случаев удобно использовать встроенные функции работы с датами.
Вы можете формировать значения параметров прямо перед выполнением запроса, используя контекст текущей даты ТекущаяДата(). Это позволяет создавать универсальные отчеты, которые всегда показывают актуальную информацию без необходимости ручной настройки дат пользователем.
Пример логики для получения данных за предыдущий месяц:
ДатаСреза = НачалоМесяца(ТекущаяДата());
НачалоПериода = НачалоМесяца(ДатаСреза - 1);
КонецПериода = КонецМесяца(ДатаСреза - 1);
Такой подход гарантирует, что даже если отчет запускается 1-го числа нового месяца, он корректно подтянет данные за весь предыдущий месяц, учитывая високосные годы и разную длину месяцев автоматически.
☑️ Проверка корректности периода
Частые ошибки и способы их устранения
Несмотря на кажущуюся простоту, разработчики регулярно сталкиваются с проблемами при фильтрации по времени. Самая частая ошибка — "потеря" последнего дня месяца из-за того, что в параметр конца периода передавалась дата без времени.
Вторая распространенная проблема — рассинхронизация времени сервера и клиента. Если сервер 1С находится в одном часовом поясе, а клиент в другом, при передаче локальной даты клиента могут возникнуть расхождения. Всегда используйте время сервера или явно конвертируйте временные зоны при необходимости.
Также стоит помнить о производительности. Если вы выбираете данные за огромный период (например, 10 лет) без дополнительных фильтров по организации или контрагенту, запрос может выполняться минуты или даже часы. Оптимизация выборки всегда начинается с сужения периода до разумных пределов.
⚠️ Внимание: Интерфейсы и поведение виртуальных таблиц могут меняться в новых версиях платформы 1С. Всегда сверяйте синтаксис параметров виртуальных таблиц в справке по вашей версии конфигурации перед внедрением в промышленную базу.
FAQ: Вопросы по установке периода
Как указать период "С начала года по текущую дату" в запросе?
Используйте функцию НачалоГода(ТекущаяДата()) для параметра начала и ТекущаяДата() для параметра конца. Не забудьте применить КонецДня() к текущей дате, если хотите включить документы, проведенные сегодня до текущего момента времени.
Почему запрос не находит документы от 31.01.2026, если я указал эту дату как конец периода?
Скорее всего, у вас поле имеет тип ДатаВремя, а параметр конца периода был установлен как 31.01.2026 00:00:00. Документы, проведенные днем 31 числа, имеют время больше нуля и не попадают в диапазон. Установите конец периода как 31.01.2026 23:59:59.
Можно ли использовать строку вместо даты в параметре запроса?
Технически можно, если строка имеет формат, понятный 1С (например, "20260101"), но это плохая практика. Всегда используйте тип Дата или ДатаВремя. Преобразование строк внутри запроса замедляет работу и может вызвать ошибки на разных локализах.
Как передать пустой период, чтобы выбрать все данные?
Для этого обычно используют специальные значения, зависящие от логики вашей конфигурации. Часто передают дату 0001.01.01 как начало и 9999.12.31 как конец. Либо используют условие ЕСТЬNULL в тексте запроса, если параметр может быть не заполнен.
Влияет ли часовой пояс на выборку периода?
Да, влияет. В клиент-серверном варианте время хранится в базе в UTC (или времени сервера). При отображении оно конвертируется во время клиента. При формировании запроса из толстого клиента или через COM-соединение убедитесь, что передаваемая дата учитывает этот сдвиг, если это критично для точности до секунды.