Как правильно рассчитать итоги в СКД при работе с несколькими наборами данных за период?

Программист 1С v8.3 (Управляемые формы) Управленческий учет
← На главную

Работа с Системой Компоновки Данных (СКД) часто преподносит сюрпризы, когда отчет, идеально работающий за один месяц, начинает выдавать некорректные цифры («кашу») при формировании за произвольный период. Особенно остро эта проблема проявляется, когда данные собираются из нескольких наборов (запросов), связанных между собой на уровне компоновщика. В данной статье мы разберем основные причины возникновения ошибок в итогах и научимся правильно настраивать ресурсы для получения достоверной информации.

Анализ проблемы: почему двоятся итоги?

Рассмотрим типичную ситуацию: у нас есть основной НаборДанных1, который выбирает список сотрудников и их плановые показатели, и НаборДанных2, подтягивающий фактические начисления или взаиморасчеты. Когда мы соединяем эти наборы в СКД, система выполняет соединение не на уровне SQL-запроса, а на уровне собственного процессора компоновки.

Разберем основные причины появления неверных сумм:

  1. Некорректная настройка параметров связи: Если связь между наборами установлена только по одному полю (например, только по сотруднику), но при этом отчет строится в разрезе периодов (месяцев), СКД может продублировать данные из второго набора для каждой строки первого, если не указано соответствие по периодам.
  2. Особенности виртуальных таблиц: Использование срезов последних (СрезПоследних) внутри запросов при расчете за период часто приводит к потере динамики изменений. Если сотрудник менял ставку внутри квартала, срез на дату окончания покажет только последнее значение, что исказит распределение сумм.
  3. Математическая ошибка агрегации: Самая частая проблема — попытка просуммировать вычисляемые поля (например, Оклад * Коэффициент) обычным агрегатом Сумма(). В итогах СКД сначала сложит все оклады, потом все коэффициенты и перемножит их, что в корне неверно.

Шаг 1. Настройка связей наборов данных

Первым делом проанализируем связи между наборами. Важно помнить, что во вкладке «Связи наборов данных» необходимо передавать не только ключевые поля (Сотрудник, Подразделение), но и параметры периода, если второй набор данных является зависимым запросом. Это позволяет ограничить выборку во втором наборе контекстом текущей строки первого набора.

Важный нюанс: проверьте, чтобы для полей связи были правильно установлены условия. Если мы хотим видеть данные помесячно, поле Период должно участвовать в связи обязательно. В противном случае, за период в 3 месяца вы получите утроенную сумму, так как данные второго набора «приклеятся» к каждой итерации первого без фильтрации по времени.

Шаг 2. Оптимизация запросов и работа с периодами

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


ВЫБРАТЬ РАЗЛИЧНЫЕ
    НАЧАЛОПЕРИОДА(КалендарныйГрафик.Дата, МЕСЯЦ) КАК Период
ПОМЕСТИТЬ ВТ_Периоды
ИЗ
    РегистрСведений.КалендарныйГрафик КАК КалендарныйГрафик
ГДЕ
    КалендарныйГрафик.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания;

Однако, когда мы соединяем этот календарь с данными о начислениях, нужно убедиться, что группировка происходит корректно. Выясним причину «каши»: если в одном месяце у сотрудника было два регистратора (документа), а связь в СКД идет только по месяцу, возникнет дублирование. Проанализируем результирующий запрос НабораДанных1:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВТ_Сводная.Пользователь КАК Пользователь,
    ВТ_Сводная.Посетитель КАК Посетитель,
    ВТ_Сводная.Период КАК Период,
    ЗанятостьНаОбъектеРаспределение.Объект КАК Объект,
    ЗанятостьНаОбъектеРаспределение.Процент КАК Процент,
    ЕСТЬNULL(НачисленияИТР.Оклад, 0) КАК Оклад,
    ЕСТЬNULL(НачисленияИТР.Начислено, 0) КАК Начислено
ИЗ
    ВТ_Сводная КАК ВТ_Сводная
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.НачисленияИТР КАК НачисленияИТР 
    ПО ВТ_Сводная.Посетитель = НачисленияИТР.Сотрудник 
    И ВТ_Сводная.Период = НачисленияИТР.Период

Если в НачисленияИТР по одному сотруднику за один период будет более одной записи, ВТ_Сводная (содержащая распределение по объектам) «размножится». В таких случаях агрегацию начислений лучше выносить в отдельный вложенный запрос или использовать СУММА(РАЗЛИЧНЫЕ ...), если это допустимо бизнес-логикой.

Шаг 3. Использование функции ВычислитьВыражениеСГруппировкойМассив

Когда простые методы не помогают и итоги все равно «лезут», на помощь приходит мощный инструмент СКД — функции работы с массивами в ресурсах. Рассмотрим ситуацию: у нас есть ресурс Дробь (коэффициент занятости) и ресурс Сумма (зарплата). Нам нужно получить итог как сумму произведений Дробь * Сумма для каждого сотрудника.

Если мы напишем в ресурсах Сумма(Дробь * ЗП), СКД на уровне общих итогов выдаст неверный результат. Правильный подход заключается в том, чтобы заставить систему сначала рассчитать суммы на уровне детальных записей (или группировки «Сотрудник»), собрать их в массив и только потом просуммировать элементы этого массива.

Синтаксис правильного расчета ресурса:

Для ресурса ЗП_Итого в поле «Выражение» на закладке «Ресурсы» следует использовать следующую конструкцию:


Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(Дробь) * Сумма(СуммаНачисления)", "Сотрудник, Период"))

Разберем, что здесь происходит:

Этот метод позволяет игнорировать лишние уровни иерархии при расчете итогов и получать математически верные значения «горизонтальных» сумм за период.

Советы по отладке и оптимизации

Для того чтобы окончательно убедиться в правильности расчетов, рекомендуем выполнить следующие действия:

  1. Проверка детальных записей: Временно выведите в отчет все поля, участвующие в расчетах, включая регистраторы и периоды в секундах. Это поможет увидеть, на каком этапе происходит дублирование строк.
  2. Роли полей: Проверьте роли полей на закладке «Наборы данных». Поле Период должно иметь соответствующую роль, а ключевые поля (ID) должны быть четко определены, чтобы СКД понимала границы записей.
  3. Использование консоли запросов: Если подозрение падает на сам SQL-запрос, выгрузите его из СКД с помощью консоли компоновки данных. Это позволит увидеть финальный текст запроса с учетом всех параметров и отборов.

Таким образом, решение проблем с «кашей» в итогах за период сводится к двум ключевым аспектам: жесткому контролю связей между наборами данных по измерениям времени и использованию продвинутых функций агрегации в ресурсах СКД. Применяя ВычислитьВыражениеСГруппировкойМассив, вы получаете полный контроль над тем, как именно суммируются ваши данные на разных уровнях иерархии отчета.

← На главную