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

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

При работе с кадровыми данными в конфигурациях на базе 1С:Предприятие 8 (например, ЗУП 3.1 или ERP) часто возникает ситуация, когда один и тот же человек за время работы в компании несколько раз увольнялся и принимался снова. В результате обычный запрос к регистрам сведений выводит «портянку» из всех исторических записей об увольнениях. Разберем подробно, как правильно составить запрос в Консоли запросов, чтобы получить только актуальную информацию о последнем увольнении, и выясним технические нюансы работы с кадровыми регистрами.

Почему в результате запроса появляются дубли?

Для начала проанализируем ситуацию: почему при выборе данных по ФИО мы видим 3-4 записи об одном и том же человеке? Выясним причину, которая кроется в архитектуре метаданных 1С. В системе разделяются понятия ФизическоеЛицо и Сотрудник.

Физическое лицо — это объект в справочнике, представляющий конкретного человека как личность (его паспортные данные, ИНН, дату рождения). Сотрудник — это запись, привязанная к конкретному трудовому договору. Если человек уволился в 2020 году и снова пришел в 2022-м, у него будет одно физическое лицо, но два разных элемента в справочнике Сотрудники. Каждое увольнение зафиксировано для своего «Сотрудника», поэтому простой выбор по регистру без группировки выдает все записи.

Решение 1: Группировка по физическому лицу и использование функции МАКСИМУМ

Самый простой и быстрый способ «схлопнуть» историю — сгруппировать данные по физическому лицу, выбрав при этом самую позднюю (максимальную) дату увольнения. Рассмотрим пример такого запроса к регистру ТекущиеКадровыеДанныеСотрудников:


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

Разберем по шагам, что здесь происходит:

  1. Мы выбираем поле ФизическоеЛицо, так как именно оно объединяет все «карточки» одного человека.
  2. Используем агрегатную функцию МАКСИМУМ для дат. Поскольку дата в 1С — это числовое значение (количество секунд), самая поздняя дата будет иметь максимальное значение.
  3. Применяем секцию ГДЕ, чтобы отсечь пустые даты увольнения (тех, кто еще работает). Учтите, что в 1С пустая дата — это 01.01.0001.
  4. Обязательно используем СГРУППИРОВАТЬ ПО, указывая все поля, к которым не применены агрегатные функции.

Решение 2: Использование регистра «ДанныеДляПодбораСотрудников»

В современных конфигурациях существует специализированный регистр ДанныеДляПодбораСотрудников. Он оптимизирован для быстрого поиска и часто содержит уже подготовленные периоды работы. Рассмотрим, как составить запрос к нему:


ВЫБРАТЬ
    ДанныеДляПодбораСотрудников.ФизическоеЛицо КАК ФИО,
    МАКСИМУМ(ДанныеДляПодбораСотрудников.Начало) КАК Начало,
    МАКСИМУМ(ДанныеДляПодбораСотрудников.Окончание) КАК Окончание
ИЗ
    РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбораСотрудников
ГДЕ
    ДанныеДляПодбораСотрудников.Начало <> ДАТАВРЕМЯ(1, 1, 1)
    И ДанныеДляПодбораСотрудников.Окончание <> ДАТАВРЕМЯ(1, 1, 1)
СГРУППИРОВАТЬ ПО
    ДанныеДляПодбораСотрудников.ФизическоеЛицо
АВТОУПОРЯДОЧИВАНИЕ

Важный момент: этот регистр обновляется системой в фоновом режиме. Если вы только что провели документ увольнения и не видите его в результате, проверьте, завершилось ли регламентное задание по обновлению данных для подбора.

Почему не работает «СрезПоследних»?

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

Сложный случай: получение дополнительных данных (должность, подразделение)

Если нам нужно не просто получить дату последнего увольнения, а еще и узнать должность, с которой человек ушел, простая группировка МАКСИМУМ нам не поможет. Мы не сможем простым способом вытащить «должность, соответствующую максимальной дате». Проанализируем профессиональный подход с использованием временных таблиц:

  1. Создаем первую временную таблицу: в ней мы получаем только ФизическоеЛицо и его МАКСИМУМ(ДатаУвольнения).
  2. Соединяем данные: во втором запросе пакета мы соединяем эту временную таблицу с исходным регистром. Соединение идет сразу по двум полям: ФизическоеЛицо и ДатаУвольнения.

Только так мы гарантированно получим запись из регистра, которая соответствует именно последнему событию, и сможем вытащить из неё любые сопутствующие реквизиты: подразделение, причину увольнения или сотрудника.


ВЫБРАТЬ
    ТекущиеКадровыеДанные.ФизическоеЛицо КАК ФизическоеЛицо,
    МАКСИМУМ(ТекущиеКадровыеДанные.ДатаУвольнения) КАК МаксДата
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
    РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанные
СГРУППИРОВАТЬ ПО
    ТекущиеКадровыеДанные.ФизическоеЛицо
;

ВЫБРАТЬ
    Регистр.Сотрудник,
    Регистр.ФизическоеЛицо,
    Регистр.ДатаУвольнения,
    Регистр.Подразделение -- Теперь мы можем безопасно взять эти данные
ИЗ
    ВТ_ПоследниеДаты КАК ПоследниеДаты
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК Регистр
    ПО ПоследниеДаты.ФизическоеЛицо = Регистр.ФизическоеЛицо
    И ПоследниеДаты.МаксДата = Регистр.ДатаУвольнения

Рекомендации по выбору источника данных

Подведем итог: какой регистр лучше использовать?

При написании условий на дату всегда помните о правиле хорошего тона в 1С: вместо Дата <> ДАТАВРЕМЯ(1,1,1) лучше использовать Дата > ДАТАВРЕМЯ(1,1,1), так как это более корректно обрабатывается индексами базы данных SQL при поиске заполненных значений.

← На главную