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

Программист 1С v8.3 (Управляемые формы)
← На главную

При работе с базами данных 1С часто возникает задача анализа активности в определенные часы. Например, нам может потребоваться получить список всех операций, совершенных только в дневную смену (с 07:00 до 19:00) за последние три месяца. Сложность заключается в том, что стандартный период в параметрах запроса ограничивает общие даты (начало и конец интервала), но не позволяет «вырезать» конкретные часы внутри каждого дня. В этой статье мы подробно разберем, как решить эту задачу с помощью встроенного языка запросов 1С.

Использование встроенной функции ЧАС() в запросах

Для решения поставленной задачи в языке запросов 1С существует специализированная функция ЧАС(). Эта функция принимает в качестве аргумента поле с типом Дата и возвращает числовое значение от 0 до 23, соответствующее часу времени, указанного в дате.

Рассмотрим базовый пример. Допустим, у нас есть документ РеализацияТоваровУслуг, и нам нужно отобрать документы, созданные с 7 утра до 7 вечера. Основная ошибка начинающих разработчиков — попытка применить условие к параметрам начала и конца периода. Однако, как правильно заметили участники обсуждения, проверять нужно не границы периода, а дату каждой конкретной операции (документа).

Проанализируем структуру условия в запросе:


ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    Реализация.Дата КАК ДатаОперации
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
    И ЧАС(Реализация.Дата) >= 7
    И ЧАС(Реализация.Дата) < 19

Разберем этот код по шагам. Условие МЕЖДУ &НачалоПериода И &КонецПериода ограничивает общую выборку (например, те самые 3 месяца). Второе условие, использующее функцию ЧАС(), работает как фильтр для каждой записи внутри этого периода, отсекая лишние часы.

Важные нюансы работы с границами интервала

При использовании функции ЧАС() крайне важно понимать, как работают границы числовых значений. Рассмотрим два варианта написания условия:

  1. Использование оператора МЕЖДУ 7 И 19: в этом случае система выберет все записи, где час равен 7, 8, ..., 18, 19. Это означает, что в выборку попадут документы, созданные в 19:59:59, так как функция ЧАС() для них все еще вернет 19.
  2. Использование строгого сравнения ЧАС(Дата) < 19: в этом случае в выборку попадут документы, созданные до 18:59:59 включительно. Как только время станет 19:00:00, документ будет исключен из результата.

Выясним, какой вариант подходит именно вам. Если ваша «дневная смена» заканчивается ровно в 19:00, используйте второй вариант (строгое меньше). Если же 19-й час включен в смену полностью, используйте МЕЖДУ или <= 19.

Обработка ночных смен (переход через полночь)

Иногда задача усложняется: необходимо выбрать операции, совершенные в ночную смену, например с 22:00 до 06:00. В этом случае простое условие МЕЖДУ не сработает, так как час не может быть одновременно больше 22 и меньше 6.

Посмотрим на пример реализации логики «ИЛИ» для ночного времени:


ГДЕ
    Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
    И (ЧАС(Реализация.Дата) >= 22 ИЛИ ЧАС(Реализация.Дата) < 6)

Такой подход позволяет корректно захватить часы конца предыдущих суток и начала следующих внутри заданного общего периода.

Производительность запроса и SARGability

Рассмотрим ситуацию с точки зрения производительности. Когда мы используем функции (такие как ЧАС(), ДЕНЬ(), ГОД()) над полями базы данных в секции ГДЕ, СУБД (например, MS SQL Server или PostgreSQL) не может эффективно использовать индексы по этим полям. Это явление называется нарушением SARGability (Search Argumentable).

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

  1. Дополнительный реквизит: При записи документа можно вычислять час и сохранять его в отдельный числовой индексированный реквизит ЧасСоздания. В этом случае запрос ГДЕ ЧасСоздания >= 7 будет работать мгновенно.
  2. Предварительная выборка: Сначала максимально ограничьте выборку по другим индексированным полям (Контрагент, Организация, Склад), а условие по времени применяйте в последнюю очередь.

Использование в Системе компоновки данных (СКД)

Если вы разрабатываете отчет, задачу можно решить еще более гибко через СКД. Мы можем не «зашивать» условие в текст запроса, а создать вычисляемое поле.

Разберем, как это сделать:

  1. В схеме компоновки данных на закладке "Вычисляемые поля" добавим поле ЧасДня.
  2. В выражении укажем Час(Дата).
  3. Теперь на закладке "Настройки" пользователь сможет самостоятельно добавить отбор: ЧасДня Больше или равно 7.

Такой подход позволяет пользователю менять интервал времени (например, сегодня смотреть с 7 до 19, а завтра с 8 до 20) без изменения кода программы.

Учет часовых поясов

Проанализируем ситуацию, когда сервер 1С и пользователи находятся в разных часовых поясах. Функция ЧАС() в запросе всегда работает с тем значением времени, которое физически записано в таблицах базы данных. Если ваша конфигурация настроена на хранение времени в формате UTC, то выборка ЧАС(Дата) = 7 вернет документы, созданные в 7 утра по Гринвичу, что для пользователя в Москве будет соответствовать 10 утра. Всегда проверяйте, в каком часовом поясе хранятся данные в вашей информационной базе, прежде чем задавать жесткие интервалы времени в коде.

Резюме

Мы выяснили, что для выборки операций по времени в 1С 8.3 наиболее правильным и простым способом является использование функции ЧАС() в секции ГДЕ запроса. Помните о том, что это условие должно применяться к полю даты конкретной операции, а не к параметрам периода. Также учитывайте влияние функций в условиях на скорость работы запроса в высоконагруженных системах и используйте возможности СКД для предоставления гибкости конечным пользователям.

← На главную