Как правильно получать данные из интервальных регистров сведений в 1С:ЗУП?

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

При разработке собственных отчетов, вариантов Универсального отчета или внешних выборок в конфигурации 1С:Зарплата и Управление Персоналом разработчики часто обращаются напрямую к интервальным регистрам сведений (например, КадроваяИсторияСотрудниковИнтервальный). Такой подход кажется привлекательным благодаря высокой скорости выборки среза данных без использования тяжелых виртуальных таблиц сведений. Однако при попытке написать простое условие на дату многие сталкиваются с некорректным поведением запроса: выбираются не те записи или пропускаются актуальные интервалы. Разберем по шагам, как устроены интервальные регистры, почему возникают ошибки и как правильно составить условие выборки.

Особенности структуры интервальных регистров в ЗУП

Для понимания логики работы запроса проанализируем внутреннее устройство интервальных регистров в 1С:ЗУП:

  1. Служебное время внутри суток. Хотя кадровый учет привязан к календарным дням, в течение одних суток по сотруднику может произойти несколько кадровых событий (например, одновременное кадровое перемещение и изменение оплаты труда). Чтобы упорядочить такие записи и выстроить четкую хронологию, механизм формирования интервалов добавляет искусственное смещение времени (секунды и минуты). Поэтому реквизит ДатаНачала редко равен строго 00:00:00, а ДатаОкончания может отличаться от стандартного конца дня 23:59:59.
  2. Открытые интервалы. Если кадровое состояние сотрудника действует бессрочно, реквизит ДатаОкончания не остается пустым, а заполняется максимальной технологической датой платформы — 31.12.3999 23:59:59.
  3. События увольнения. Интервальный регистр хранит всю цепочку состояний. После проведения документа увольнения формируется интервал с видом кадрового события «Увольнение», который также продолжается до фиктивной максимальной даты. Без дополнительного фильтра запрос вернет уволенного сотрудника как действующего.
  4. Служебный характер данных. Интервальные регистры являются подчиненными (ведомыми). Их содержимое формируется служебными процедурами (в частности, ОбновитьИнтервальныйРегистрСведений) при записи базовых периодических регистров. При программных сбоях или нехронологическом проведении документов данные интервалов могут рассинхронизироваться.

Корректные условия для получения среза данных на дату

Выясним причину типичной ошибки: если написать простое условие с оператором МЕЖДУ или сравнить дату начала без учета времени, запрос на определенную дату возьмет не актуальную, а предыдущую запись интервала. Чтобы гарантированно захватить нужный интервал, целевую дату необходимо приводить к концу дня.

Посмотрим на пример правильного условия для выборки кадрового среза на конкретную дату:


ВЫБРАТЬ
    Регистр.Сотрудник,
    Регистр.Подразделение,
    Регистр.Должность,
    Регистр.ВидСобытия
ИЗ
    РегистрСведений.КадроваяИсторияСотрудниковИнтервальный КАК Регистр
ГДЕ
    Регистр.ДатаНачала <= КОНЕЦПЕРИОДА(&Период, ДЕНЬ)
    И Регистр.ДатаОкончания >= КОНЕЦПЕРИОДА(&Период, ДЕНЬ)
    И Регистр.ВидСобытия <> ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение)
    И НЕ Регистр.ПустойИнтервал

Разберем подробнее, что делают эти условия:

  1. Конструкция КОНЕЦПЕРИОДА(&Период, ДЕНЬ) гарантирует, что даже если в поле ДатаНачала записано смещение на несколько секунд вперед от начала дня (например, 01.08.2026 00:00:01), условие ДатаНачала <= 01.08.2026 23:59:59 успешно выполнится.
  2. Проверка ДатаОкончания >= КОНЕЦПЕРИОДА(&Период, ДЕНЬ) гарантирует, что срез попадет внутрь действующего интервала, включая открытые записи с датой 3999-12-31.
  3. Отбор ВидСобытия <> ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) исключает сотрудников, у которых интервал действует после даты увольнения.
  4. Флаг НЕ Регистр.ПустойИнтервал (если реквизит предусмотрен в структуре регистра) отсекает служебные фиктивные интервалы.

Если в вашем отчете параметр периода может быть не заполнен (например, требуется получить срез на текущий момент при пустом значении), дополним условие обработкой пустой даты:


ГДЕ
    Регистр.ДатаНачала <= ВЫБОР 
        КОГДА &Период = ДАТАВРЕМЯ(1, 1, 1) ТОГДА ДАТАВРЕМЯ(3999, 12, 31, 23, 59, 59) 
        ИНАЧЕ КОНЕЦПЕРИОДА(&Период, ДЕНЬ) 
    КОНЕЦ
    И Регистр.ДатаОкончания >= ВЫБОР 
        КОГДА &Период = ДАТАВРЕМЯ(1, 1, 1) ТОГДА ДАТАВРЕМЯ(3999, 12, 31, 23, 59, 59) 
        ИНАЧЕ КОНЕЦПЕРИОДА(&Период, ДЕНЬ) 
    КОНЕЦ

Выборка данных за интервал дат (пересечение периодов)

Если перед нами стоит задача отобрать кадровые изменения или состояния сотрудников не на одну дату, а за произвольный период времени, используем классическое условие пересечения двух отрезков времени:


ГДЕ
    Регистр.ДатаНачала <= КОНЕЦПЕРИОДА(&ДатаОкончания, ДЕНЬ)
    И Регистр.ДатаОкончания >= НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ)

Такая конструкция вернет все записи регистра, действие которых хотя бы частично пересекается с выбранным временным диапазоном.

Альтернативные способы получения кадровых данных

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

  1. Базовый срез последних. Использование стандартной виртуальной таблицы РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(&Период). Этот способ полностью поддерживается Универсальным отчетом и компоновкой данных без ручной обработки секунд и миллисекунд. На небольших базах разница в производительности практически незаметна.
  2. Программный API конфигурации. В отчетах и обработках, поддерживающих исполняемый код, рекомендуется вызывать типовые методы общего модуля КадровыйУчет:
    
    // Получение кадровых данных на дату в виде таблицы
    КадровыеДанные = КадровыйУчет.КадровыеДанныеСотрудников(Истина, Сотрудники, "Подразделение,Должность", &Период);
    
    // Получение списка работающих сотрудников
    ТаблицаСотрудников = КадровыйУчет.СотрудникиОрганизации(Организация, &Период);
    
    Эти функции самостоятельно учитывают все тонкости интервалов, увольнений, совмещений и временных смещений.
  3. Механизм общих наборов данных. В сложных СКД используются типовые представления вида Представления_ТаблицаРегистра_КадроваяИсторияСотрудников с вызовом процедуры ЗарплатаКадрыОбщиеНаборыДанных.ЗаполнитьОбщиеИсточникиДанныхОтчета(ЭтотОбъект) перед компоновкой данных. Это стандартный архитектурный подход ЗУП 3 для тиражных отчетов.
  4. Разработка расширений для облачных баз. Если работа ведется в облачной версии (1С:Фреш), где нельзя менять конфигурацию, кастомный отчет с использованием программного API ЗУП можно оформить в виде расширения конфигурации, работающего в безопасном режиме.
← На главную