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