При работе с кадровыми данными в конфигурациях на базе 1С:Предприятие 8 (например, ЗУП 3.1 или ERP) часто возникает ситуация, когда один и тот же человек за время работы в компании несколько раз увольнялся и принимался снова. В результате обычный запрос к регистрам сведений выводит «портянку» из всех исторических записей об увольнениях. Разберем подробно, как правильно составить запрос в Консоли запросов, чтобы получить только актуальную информацию о последнем увольнении, и выясним технические нюансы работы с кадровыми регистрами.
Для начала проанализируем ситуацию: почему при выборе данных по ФИО мы видим 3-4 записи об одном и том же человеке? Выясним причину, которая кроется в архитектуре метаданных 1С. В системе разделяются понятия ФизическоеЛицо и Сотрудник.
Физическое лицо — это объект в справочнике, представляющий конкретного человека как личность (его паспортные данные, ИНН, дату рождения). Сотрудник — это запись, привязанная к конкретному трудовому договору. Если человек уволился в 2020 году и снова пришел в 2022-м, у него будет одно физическое лицо, но два разных элемента в справочнике Сотрудники. Каждое увольнение зафиксировано для своего «Сотрудника», поэтому простой выбор по регистру без группировки выдает все записи.
Самый простой и быстрый способ «схлопнуть» историю — сгруппировать данные по физическому лицу, выбрав при этом самую позднюю (максимальную) дату увольнения. Рассмотрим пример такого запроса к регистру ТекущиеКадровыеДанныеСотрудников:
ВЫБРАТЬ
ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо КАК ФИО,
МАКСИМУМ(ТекущиеКадровыеДанныеСотрудников.ДатаПриема) КАК ДатаПриема,
МАКСИМУМ(ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения) КАК ДатаУвольнения
ИЗ
РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ГДЕ
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения <> ДАТАВРЕМЯ(1, 1, 1)
СГРУППИРОВАТЬ ПО
ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо
АВТОУПОРЯДОЧИВАНИЕ
Разберем по шагам, что здесь происходит:
ФизическоеЛицо, так как именно оно объединяет все «карточки» одного человека.МАКСИМУМ для дат. Поскольку дата в 1С — это числовое значение (количество секунд), самая поздняя дата будет иметь максимальное значение.ГДЕ, чтобы отсечь пустые даты увольнения (тех, кто еще работает). Учтите, что в 1С пустая дата — это 01.01.0001.СГРУППИРОВАТЬ ПО, указывая все поля, к которым не применены агрегатные функции.В современных конфигурациях существует специализированный регистр ДанныеДляПодбораСотрудников. Он оптимизирован для быстрого поиска и часто содержит уже подготовленные периоды работы. Рассмотрим, как составить запрос к нему:
ВЫБРАТЬ
ДанныеДляПодбораСотрудников.ФизическоеЛицо КАК ФИО,
МАКСИМУМ(ДанныеДляПодбораСотрудников.Начало) КАК Начало,
МАКСИМУМ(ДанныеДляПодбораСотрудников.Окончание) КАК Окончание
ИЗ
РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбораСотрудников
ГДЕ
ДанныеДляПодбораСотрудников.Начало <> ДАТАВРЕМЯ(1, 1, 1)
И ДанныеДляПодбораСотрудников.Окончание <> ДАТАВРЕМЯ(1, 1, 1)
СГРУППИРОВАТЬ ПО
ДанныеДляПодбораСотрудников.ФизическоеЛицо
АВТОУПОРЯДОЧИВАНИЕ
Важный момент: этот регистр обновляется системой в фоновом режиме. Если вы только что провели документ увольнения и не видите его в результате, проверьте, завершилось ли регламентное задание по обновлению данных для подбора.
Часто программисты пытаются использовать виртуальную таблицу СрезПоследних, как это принято в периодических регистрах. Однако в случае с регистром ТекущиеКадровыеДанныеСотрудников это невозможно. Посмотрим на причину: данный регистр является непериодическим. Он сам по себе хранит только текущее (актуальное) состояние данных. Виртуальные таблицы срезов доступны только для периодических регистров, таких как КадроваяИсторияСотрудников.
Если нам нужно не просто получить дату последнего увольнения, а еще и узнать должность, с которой человек ушел, простая группировка МАКСИМУМ нам не поможет. Мы не сможем простым способом вытащить «должность, соответствующую максимальной дате». Проанализируем профессиональный подход с использованием временных таблиц:
ФизическоеЛицо и его МАКСИМУМ(ДатаУвольнения).ФизическоеЛицо и ДатаУвольнения.Только так мы гарантированно получим запись из регистра, которая соответствует именно последнему событию, и сможем вытащить из неё любые сопутствующие реквизиты: подразделение, причину увольнения или сотрудника.
ВЫБРАТЬ
ТекущиеКадровыеДанные.ФизическоеЛицо КАК ФизическоеЛицо,
МАКСИМУМ(ТекущиеКадровыеДанные.ДатаУвольнения) КАК МаксДата
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанные
СГРУППИРОВАТЬ ПО
ТекущиеКадровыеДанные.ФизическоеЛицо
;
ВЫБРАТЬ
Регистр.Сотрудник,
Регистр.ФизическоеЛицо,
Регистр.ДатаУвольнения,
Регистр.Подразделение -- Теперь мы можем безопасно взять эти данные
ИЗ
ВТ_ПоследниеДаты КАК ПоследниеДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК Регистр
ПО ПоследниеДаты.ФизическоеЛицо = Регистр.ФизическоеЛицо
И ПоследниеДаты.МаксДата = Регистр.ДатаУвольнения
Подведем итог: какой регистр лучше использовать?
СрезПоследних.При написании условий на дату всегда помните о правиле хорошего тона в 1С: вместо Дата <> ДАТАВРЕМЯ(1,1,1) лучше использовать Дата > ДАТАВРЕМЯ(1,1,1), так как это более корректно обрабатывается индексами базы данных SQL при поиске заполненных значений.