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