Как составить запрос в 1С 8.3 для получения списка сотрудников, работающих в определенном периоде?

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

При работе с запросами в 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. Сотрудник принят не позже окончания нашего периода: ДатаПриема <= &ДатаКонца.
  2. Сотрудник уволен не раньше начала нашего периода ИЛИ он еще не уволен: (ДатаУвольнения >= &ДатаНачала ИЛИ ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1)).

Посмотрим на итоговый правильный запрос:


ВЫБРАТЬ
    Сотрудники.Наименование КАК ФИО,
    Сотрудники.Должность КАК Должность
ИЗ
    Справочник.Сотрудники КАК Сотрудники
ГДЕ
    Сотрудники.ДатаПриема <= &ДК
    И (Сотрудники.ДатаУвольнения >= &ДН 
       ИЛИ Сотрудники.ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1))

Где &ДН — начало периода (01.02.2023 00:00:00), а &ДК — окончание периода (22.10.2023 23:59:59).

Обработка пустых дат и особенностей 1С

В системе 1С реквизиты типа Дата не могут быть NULL (если только это не результат соединения таблиц). Пустая дата в 1С — это 01.01.0001 00:00:00. Чтобы проверить, что сотрудник еще не уволен, мы сравниваем его дату увольнения с литералом ДАТАВРЕМЯ(1, 1, 1).

Важные нюансы при работе в «Консоли запросов»:

  1. Если при нажатии на кнопку «Параметры» вы видите ошибку «Индекс находится за границами массива», это означает, что консоль не смогла распознать параметры из-за синтаксической ошибки в тексте запроса выше. Проверьте правильность написания &НазваниеПараметра.
  2. Всегда проверяйте тип параметра в консоли. Он должен быть Дата, а не Строка.
  3. Для получения всех записей за 22 октября используйте в параметрах КонецДня, чтобы время было 23:59:59.

Оптимизация и производительность

Проанализируем вопрос производительности. Если ваша база содержит тысячи сотрудников, старайтесь не использовать функции обработки дат в условии ГДЕ (например, ГДЕ ГОД(ДатаПриема) = 2023). Такие конструкции блокируют использование индексов, и запрос будет выполняться долго (сканирование всей таблицы).

Правильный подход — подготовить чистые значения дат в коде и передать их как параметры, чтобы запрос сравнивал «поле» с «конкретным значением». Это обеспечит максимальную скорость работы программы.

Таким образом, мы выяснили, что для решения задачи необходимо использовать правильные литералы ДАТАВРЕМЯ, учитывать время в границах периода и применять логику пересечения интервалов для включения всех работающих сотрудников.

← На главную