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

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

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

Выясним основные причины появления дублей строк в отчете:

  1. Множественные записи в кадровых данных. Человек (физическое лицо) может числиться на внутреннем совместительстве, совмещать должности или иметь повторный прием на работу после увольнения. Если отчет формируется по справочнику ФизическиеЛица или СотрудникиОрганизаций без учета основного места работы, для каждой активной должности создается отдельная строка.
  2. Связь «один ко многим» с дополнительными регистрами. При левом соединении с регистром сведений (например, Заметки) строка сотрудника дублируется ровно столько раз, сколько заметок к нему привязано.
  3. Получение кадровой истории без среза. Если срез последних не используется, выбираются все исторические кадровые переводы и изменения подразделений.
  4. Ограничения СУБД на группировку строк неограниченной длины. При попытке сгруппировать данные в тексте запроса по текстовому полю (например, содержанию заметки) СУБД возвращает ошибку о недопустимом поле для группировки.

Способ 1. Приведение строк неограниченной длины с помощью оператора ВЫРАЗИТЬ

Разберем ситуацию, когда группировка выполняется непосредственно на уровне запроса 1С. Поля типа Строка неограниченной длины хранятся в СУБД в специальных форматах (например, VARCHAR(MAX) или TEXT), по которым невозможно выполнить операцию СГРУППИРОВАТЬ ПО. Чтобы обойти это ограничение, приведем строку к фиксированной длине с помощью оператора ВЫРАЗИТЬ.

Однако простого приведения типа недостаточно, если у одного сотрудника есть несколько разных заметок: разные строки все равно разобьют результат на несколько записей. Поэтому в секции ВЫБРАТЬ применим агрегатную функцию к выраженному полю, а само поле исключим из секции СГРУППИРОВАТЬ ПО.

Посмотрим на пример запроса:


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

В данном случае мы ограничили длину текста заметки до 1000 символов и выбрали максимальное строковое значение, что позволяет полностью свернуть дубли в результирующей таблице.

Способ 2. Агрегация строк средствами СКД без обрезки длины

Рассмотрим случай, когда обрезать текст заметки нельзя и требуется вывести все имеющиеся заметки по сотруднику в одну ячейку через перенос строки. В СКД для этого не требуется делать группировку в запросе — агрегацию можно выполнить на вкладке Ресурсы.

Разберем по шагам порядок настройки:

  1. В тексте запроса оставляем поле Содержание без ограничений по длине и без секции СГРУППИРОВАТЬ ПО.
  2. Переходим на вкладку Ресурсы в схеме компоновки данных.
  3. Добавляем поле Содержание в список ресурсов.
  4. В колонке Выражение указываем стандартную функцию агрегации строк: СоединитьСтроки(Содержание, Символы.ПС) или расширенное выражение с предварительным исключением дубликатов текста:
    
    СоединитьСтроки(ВычислитьВыражениеСГруппировкойТаблицаЗначений("Содержание", "Содержание"), Символы.ПС)
    
  5. В настройках структуры отчета на вкладке Настройки создаем группировку по сотруднику или физическому лицу, а в выбранные поля выводим кадровые данные и наш ресурс Содержание.

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

Способ 3. Получение только последней актуальной записи через вложенный запрос

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

Посмотрим на пример запроса:


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

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

Способ 4. Исключение внутреннего совместительства и разделение наборов данных

Проанализируем ситуацию, когда дублирование вызвано кадровыми особенностями (работа на полставки, совместительство). Чтобы отчет выводил сотрудника строго один раз по основному месту работы, добавим фильтрацию в условия запроса или отборы отчета:


ГДЕ
    СотрудникиОрганизаций.ВидЗанятости = ЗНАЧЕНИЕ(Перечисление.ВидыЗанятостиВОрганизации.ОсновноеМестоРаботы)

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

  1. НаборДанных1 (Запрос) — выбирает кадровые данные из справочника сотрудников и регистров сведений.
  2. НаборДанных2 (Запрос) — выбирает информацию из регистра заметок.
  3. На вкладке Связи наборов данных настраиваем связь между наборами по полю Сотрудник или Физлицо.

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

← На главную