При работе с запросами в 1С:Предприятии 8.3 начинающие разработчики часто сталкиваются с трудностями при обработке полей типа Дата. Основные проблемы возникают из-за путаницы в синтаксисе между языком программирования и языком запросов, а также из-за нюансов хранения времени в датах. Разберем подробно, как правильно реализовать выборку сотрудников, работавших в заданном интервале, и исправить типичные синтаксические ошибки.
Рассмотрим типичную ошибку из примера: использование одинарных кавычек и точек для обозначения даты непосредственно в тексте запроса. В языке запросов 1С конструкция типа '2023.10.22' воспринимается системой как синтаксическая ошибка или как обычная строка, которую невозможно напрямую сравнить с полем типа Дата.
Выясним причину: в 1С тип Дата — это сложный тип, который всегда содержит и календарную дату, и время (часы, минуты, секунды). Для написания даты «жестко» в тексте запроса (использования литерала) существует строго определенная функция — ДАТАВРЕМЯ.
Вариант исправления с использованием литерала:
ВЫБРАТЬ
Сотрудники.Наименование,
Сотрудники.Должность
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
Сотрудники.ДатаПриема >= ДАТАВРЕМЯ(2023, 2, 1, 0, 0, 0)
В данном примере мы четко указываем год, месяц, день и время. Если время не критично, можно использовать сокращенную форму ДАТАВРЕМЯ(2023, 2, 1), тогда время автоматически установится в 00:00:00.
Проанализируем более профессиональный подход. Написание дат внутри текста запроса считается «плохим тоном», так как это делает запрос негибким. Правильно передавать даты через параметры. Это позволяет избежать ошибок синтаксиса и учитывать особенности времени.
Рассмотрим, как это реализовать в коде 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Наименование,
| Сотрудники.Должность
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
|ГДЕ
| Сотрудники.ДатаПриема >= &ДатаНачала
| И Сотрудники.ДатаПриема <= &ДатаКонца";
// Обратите внимание: в коде мы используем кавычки и формат ГГГГММДД
Запрос.УстановитьПараметр("ДатаНачала", '20230201000000');
Запрос.УстановитьПараметр("ДатаКонца", '20231022235959');
Важно помнить: если мы сравниваем дату с 22.10.2023, то без указания времени система подставит 00:00:00. Если сотрудник был принят в 10 утра этого дня, он не попадет в выборку при условии <=. Поэтому для корректной работы всегда используйте функции НачалоДня и КонецДня при передаче параметров.
Теперь разберем самую важную часть — логику отбора. Задача «вывести список сотрудников, работающих на период» часто понимается неверно. Если мы используем простое условие Сотрудники.ДатаПриема МЕЖДУ &ДатаНачала И &ДатаКонца, мы получим только тех, кто устроился в этот период. Но как быть с теми, кто устроился год назад и продолжает работать? Они ведь тоже работали в этот период!
Правильная логическая формула для нахождения всех работавших сотрудников выглядит так:
ДатаПриема <= &ДатаКонца.(ДатаУвольнения >= &ДатаНачала ИЛИ ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1)).Посмотрим на итоговый правильный запрос:
ВЫБРАТЬ
Сотрудники.Наименование КАК ФИО,
Сотрудники.Должность КАК Должность
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
Сотрудники.ДатаПриема <= &ДК
И (Сотрудники.ДатаУвольнения >= &ДН
ИЛИ Сотрудники.ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1))
Где &ДН — начало периода (01.02.2023 00:00:00), а &ДК — окончание периода (22.10.2023 23:59:59).
В системе 1С реквизиты типа Дата не могут быть NULL (если только это не результат соединения таблиц). Пустая дата в 1С — это 01.01.0001 00:00:00. Чтобы проверить, что сотрудник еще не уволен, мы сравниваем его дату увольнения с литералом ДАТАВРЕМЯ(1, 1, 1).
Важные нюансы при работе в «Консоли запросов»:
&НазваниеПараметра.Дата, а не Строка.КонецДня, чтобы время было 23:59:59.Проанализируем вопрос производительности. Если ваша база содержит тысячи сотрудников, старайтесь не использовать функции обработки дат в условии ГДЕ (например, ГДЕ ГОД(ДатаПриема) = 2023). Такие конструкции блокируют использование индексов, и запрос будет выполняться долго (сканирование всей таблицы).
Правильный подход — подготовить чистые значения дат в коде и передать их как параметры, чтобы запрос сравнивал «поле» с «конкретным значением». Это обеспечит максимальную скорость работы программы.
Таким образом, мы выяснили, что для решения задачи необходимо использовать правильные литералы ДАТАВРЕМЯ, учитывать время в границах периода и применять логику пересечения интервалов для включения всех работающих сотрудников.