Почему в отчете СКД некорректно рассчитываются итоги и как это исправить?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Выясним причину поведения платформы

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

  1. Если в отчете выводится только группировка верхнего уровня (например, Сотрудник), а поле нижнего уровня (ВнутреннийЗаказ) не выведено в детальные записи или структуру отчета, оптимизатор СКД исключает детальное поле из результирующей выборки к СУБД.
  2. Платформа выполняет группировку непосредственно на уровне базы данных. В результате выражение 1 КАК ВсегоЗаказов возвращается сервером СУБД один раз для каждой свернутой строки сотрудника.
  3. Агрегатная функция Сумма(ВсегоЗаказов) на уровне компоновщика суммирует уже единственную возвращенную единицу, выдавая некорректный итог.

Способ 1. Использование встроенных функций агрегации в ресурсах (Рекомендуемый подход)

Рассмотрим правильный подход к подсчету количества записей в СКД без добавления искусственных полей-констант в запрос. Проанализируем шаги настройки:

  1. В тексте запроса оставляем только реальные поля: Сотрудник, ВнутреннийЗаказ.
  2. Переходим на вкладку Ресурсы схемы компоновки данных.
  3. Добавляем поле ВнутреннийЗаказ в список ресурсов.
  4. В колонке Выражение указываем формулу подсчета количества:

Количество(Различные ВнутреннийЗаказ)

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

Способ 2. Агрегация данных в запросе с явной группировкой

Если требуется получить готовое числовое поле непосредственно из набора данных запроса, заменим константу на агрегатную функцию СУБД с обязательной группировкой по ключевым полям. Посмотрим на пример текста запроса:


ВЫБРАТЬ
    ВТСобранныеЗаказы.Сотрудник КАК Сотрудник,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТСобранныеЗаказы.ВнутреннийЗаказ) КАК ВсегоЗаказов
ИЗ
    ВТСобранныеЗаказы КАК ВТСобранныеЗаказы
СГРУППИРОВАТЬ ПО
    ВТСобранныеЗаказы.Сотрудник

После этого на вкладке Ресурсы для поля ВсегоЗаказов задаем стандартное выражение Сумма(ВсегоЗаказов). Поскольку группировка зафиксирована в самом запросе, платформа не сможет схлопнуть строки некорректно.

Способ 3. Установка флага «Обязательное» для детального поля

Разберем вариант, когда структуру запроса менять нежелательно, но необходимо запретить оптимизатору СКД исключать детальные поля:

  1. Открываем вкладку Наборы данных.
  2. В таблице полей находим поле детальных записей (например, ВнутреннийЗаказ).
  3. Устанавливаем для него флаг Обязательное (колонку с флажком «Авто»/«Обязательное»).

Этот флаг сообщает оптимизатору СКД, что поле должно всегда присутствовать в итоговом SQL-запросе к СУБД независимо от настроек структуры отчета. Детальные строки не будут свернуты на уровне сервера базы данных, и расчет Сумма(ВсегоЗаказов) отработает верно.

Способ 4. Использование временной таблицы в пакете запросов

Еще один рабочий способ — выгрузка предварительных данных во временную таблицу. Если поместить детальные строки с константой 1 КАК ВсегоЗаказов во временную таблицу и затем в итоговом запросе пакета выбрать данные из нее, оптимизатор СКД сохранит структуру выборки и вернет все строки, что позволит агрегатной функции Сумма() рассчитать итог по всем элементам.

Способ 5. Настройка поля «Рассчитывать по...» и контекстные функции СКД

Если требуется выводить единицу на уровне детальных записей, а на уровне группировок вычислять общее количество, настроим вкладку Ресурсы раздельно по уровням:

  1. В первой строке ресурса ВсегоЗаказов указываем выражение 1 и в колонке Рассчитывать по... выбираем детальные записи.
  2. Во второй строке ресурса ВсегоЗаказов прописываем агрегатное выражение для группировок:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Количество(Различные ВнутреннийЗаказ)", "Сотрудник"))

Такая гибкая настройка гарантирует точный расчет показателей на всех уровнях иерархии отчета без изменения текста исходных запросов.

← На главную