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