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