При работе с базами данных 1С часто возникает задача анализа активности в определенные часы. Например, нам может потребоваться получить список всех операций, совершенных только в дневную смену (с 07:00 до 19:00) за последние три месяца. Сложность заключается в том, что стандартный период в параметрах запроса ограничивает общие даты (начало и конец интервала), но не позволяет «вырезать» конкретные часы внутри каждого дня. В этой статье мы подробно разберем, как решить эту задачу с помощью встроенного языка запросов 1С.
Для решения поставленной задачи в языке запросов 1С существует специализированная функция ЧАС(). Эта функция принимает в качестве аргумента поле с типом Дата и возвращает числовое значение от 0 до 23, соответствующее часу времени, указанного в дате.
Рассмотрим базовый пример. Допустим, у нас есть документ РеализацияТоваровУслуг, и нам нужно отобрать документы, созданные с 7 утра до 7 вечера. Основная ошибка начинающих разработчиков — попытка применить условие к параметрам начала и конца периода. Однако, как правильно заметили участники обсуждения, проверять нужно не границы периода, а дату каждой конкретной операции (документа).
Проанализируем структуру условия в запросе:
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
Реализация.Дата КАК ДатаОперации
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И ЧАС(Реализация.Дата) >= 7
И ЧАС(Реализация.Дата) < 19
Разберем этот код по шагам. Условие МЕЖДУ &НачалоПериода И &КонецПериода ограничивает общую выборку (например, те самые 3 месяца). Второе условие, использующее функцию ЧАС(), работает как фильтр для каждой записи внутри этого периода, отсекая лишние часы.
При использовании функции ЧАС() крайне важно понимать, как работают границы числовых значений. Рассмотрим два варианта написания условия:
МЕЖДУ 7 И 19: в этом случае система выберет все записи, где час равен 7, 8, ..., 18, 19. Это означает, что в выборку попадут документы, созданные в 19:59:59, так как функция ЧАС() для них все еще вернет 19.ЧАС(Дата) < 19: в этом случае в выборку попадут документы, созданные до 18:59:59 включительно. Как только время станет 19:00:00, документ будет исключен из результата.Выясним, какой вариант подходит именно вам. Если ваша «дневная смена» заканчивается ровно в 19:00, используйте второй вариант (строгое меньше). Если же 19-й час включен в смену полностью, используйте МЕЖДУ или <= 19.
Иногда задача усложняется: необходимо выбрать операции, совершенные в ночную смену, например с 22:00 до 06:00. В этом случае простое условие МЕЖДУ не сработает, так как час не может быть одновременно больше 22 и меньше 6.
Посмотрим на пример реализации логики «ИЛИ» для ночного времени:
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И (ЧАС(Реализация.Дата) >= 22 ИЛИ ЧАС(Реализация.Дата) < 6)
Такой подход позволяет корректно захватить часы конца предыдущих суток и начала следующих внутри заданного общего периода.
Рассмотрим ситуацию с точки зрения производительности. Когда мы используем функции (такие как ЧАС(), ДЕНЬ(), ГОД()) над полями базы данных в секции ГДЕ, СУБД (например, MS SQL Server или PostgreSQL) не может эффективно использовать индексы по этим полям. Это явление называется нарушением SARGability (Search Argumentable).
Если в вашей базе миллионы документов за 3 месяца, запрос может выполняться медленно, так как серверу придется прочитать каждую запись, чтобы вычислить значение часа. Проанализируем способы оптимизации:
ЧасСоздания. В этом случае запрос ГДЕ ЧасСоздания >= 7 будет работать мгновенно.Если вы разрабатываете отчет, задачу можно решить еще более гибко через СКД. Мы можем не «зашивать» условие в текст запроса, а создать вычисляемое поле.
Разберем, как это сделать:
ЧасДня.Час(Дата).ЧасДня Больше или равно 7.Такой подход позволяет пользователю менять интервал времени (например, сегодня смотреть с 7 до 19, а завтра с 8 до 20) без изменения кода программы.
Проанализируем ситуацию, когда сервер 1С и пользователи находятся в разных часовых поясах. Функция ЧАС() в запросе всегда работает с тем значением времени, которое физически записано в таблицах базы данных. Если ваша конфигурация настроена на хранение времени в формате UTC, то выборка ЧАС(Дата) = 7 вернет документы, созданные в 7 утра по Гринвичу, что для пользователя в Москве будет соответствовать 10 утра. Всегда проверяйте, в каком часовом поясе хранятся данные в вашей информационной базе, прежде чем задавать жесткие интервалы времени в коде.
Мы выяснили, что для выборки операций по времени в 1С 8.3 наиболее правильным и простым способом является использование функции ЧАС() в секции ГДЕ запроса. Помните о том, что это условие должно применяться к полю даты конкретной операции, а не к параметрам периода. Также учитывайте влияние функций в условиях на скорость работы запроса в высоконагруженных системах и используйте возможности СКД для предоставления гибкости конечным пользователям.