Как получить прежние и новые кадровые данные в отчете по перемещениям сотрудников в 1С:УНФ

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

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

В этой статье мы подробно разберем, как правильно составить запрос, чтобы избежать дублирования строк и корректно получить «прежнюю» должность и подразделение, даже если в один день по сотруднику было несколько движений.

Анализ проблемы: почему стандартное соединение может не работать

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

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

Решение №1: Использование метода «двойного левого соединения»

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

Рассмотрим пример запроса:


ВЫБРАТЬ
    КадровоеПеремещениеСотрудники.Ссылка КАК Ссылка,
    КадровоеПеремещениеСотрудники.Сотрудник КАК Сотрудник,
    ТутПрежниеКадровыеДанные.СтруктурнаяЕдиница КАК СтруктурнаяЕдиницаПрежняя,
    КадровоеПеремещениеСотрудники.СтруктурнаяЕдиница КАК СтруктурнаяЕдиницаНовая,
    ТутПрежниеКадровыеДанные.Должность КАК ДолжностьПрежняя,
    КадровоеПеремещениеСотрудники.Должность КАК ДолжностьНовая,
    КадровоеПеремещениеСотрудники.Период КАК Период
ИЗ
    Документ.КадровоеПеремещение.Сотрудники КАК КадровоеПеремещениеСотрудники
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Сотрудники КАК ТутПрежниеКадровыеДанные
        ПО КадровоеПеремещениеСотрудники.Сотрудник = ТутПрежниеКадровыеДанные.Сотрудник
            И КадровоеПеремещениеСотрудники.Период > ТутПрежниеКадровыеДанные.Период
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Сотрудники КАК РегБолееПоздний
        ПО КадровоеПеремещениеСотрудники.Сотрудник = РегБолееПоздний.Сотрудник
            И РегБолееПоздний.Период > ТутПрежниеКадровыеДанные.Период
            И КадровоеПеремещениеСотрудники.Период > РегБолееПоздний.Период
ГДЕ
    КадровоеПеремещениеСотрудники.Ссылка.Проведен = ИСТИНА
    И РегБолееПоздний.Сотрудник ЕСТЬ NULL

Разберем по шагам, как это работает:

  1. Первое соединение с ТутПрежниеКадровыеДанные находит все записи в регистре, которые были сделаны раньше даты текущего перемещения.
  2. Второе соединение с РегБолееПоздний пытается найти записи, которые находятся между датой из первого соединения и датой документа.
  3. Условие ГДЕ РегБолееПоздний.Сотрудник ЕСТЬ NULL отсекает все варианты, кроме того, где «промежуточной» записи не нашлось. Это и будет максимально близкая к документу прошлая запись.

Решение №2: Оптимальный подход через виртуальные таблицы (СрезПоследних)

Хотя первый метод работает, в платформе 1С есть более эффективный инструмент — виртуальная таблица СрезПоследних. Чтобы получить данные «до» перемещения, нам нужно получить состояние на момент времени документа, но не включая движения самого документа.

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

  1. Выбираем необходимые данные из документа во временную таблицу.
  2. Для каждой строки документа вычисляем момент времени (или Период - 1 секунда).
  3. Присоединяем виртуальную таблицу СрезПоследних, передавая в неё рассчитанный период.

Пример реализации в запросе:


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

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

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

Особенности работы с данными в УНФ

Выясним причину, по которой иногда данные могут «двоиться» или не находиться. В 1С:УНФ регистр Сотрудники является периодическим в пределах секунды. Если документ перемещения записан той же секундой, что и прием на работу (редко, но бывает при импорте данных), обычное условие Период = Период выдаст уже новое состояние.

Рассмотрим рекомендации для обеспечения точности отчета:

Таким образом, мы рассмотрели два основных способа решения задачи: через чистое SQL-подобное соединение физических таблиц и через использование механизмов платформы 1С. Второй способ является предпочтительным с точки зрения производительности и читаемости кода.

← На главную