При построении отчетов и выборок в платформе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда плоская таблица запроса возвращает корректные данные, но при добавлении секции ИТОГИ ПО расчетные суммы многократно увеличиваются, строки дублируются, а при обходе выборки поля содержат пустые значения. Разберем детально, почему так происходит, как устроен механизм расчета итогов и как правильно организовать обработку результатов запроса.
Проанализируем распространенную ошибку, когда результат запроса проверяется через метод Запрос.Выполнить().Выгрузить(). Если в тексте запроса присутствует секция ИТОГИ, метод Выгрузить() по умолчанию помещает в результирующую таблицу значений не только детальные записи, но и промежуточные строки итогов.
В такой таблице одна и та же реализация визуально встречается несколько раз:
NULL или пустые значения).Если требуется получить визуальное дерево или правильную плоскую структуру, используем следующие подходы:
Дерево = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
СГРУППИРОВАТЬ ПО вместо ИТОГИ ПО, если промежуточные расчетные уровни в запросе не требуются, а нужна лишь агрегация данных на одном уровне.Выясним причину, из-за которой агрегатные функции СУММА() в секции ИТОГИ возвращают завышенные результаты. В отчете присутствуют поля документа реализации и документа оплаты. Если к одной накладной проведено несколько платежей (или частичных оплат), левое или внутреннее соединение размножает строку реализации по количеству строк оплат.
В детальных строках плоской таблицы сумма документа может выглядеть привычно, но директива ИТОГИ СУММА(РеализацияНаСумму) ПО ТорговыйАгент выполняет простое арифметическое суммирование по всем строкам выборки. Если документ оплаты разбился на 4 строки, сумма реализации суммируется 4 раза.
Чтобы избежать искажения сумм, разделим сбор данных на предварительные этапы во временных таблицах:
Рассмотрим, почему при обходе выборки возникают пустые значения. В строках группировок верхнего уровня детальные поля не определены и равны NULL. Доступны только само группировочное поле и поля, для которых в секции ИТОГИ явно указаны агрегатные функции (СУММА, МИНИМУМ, МАКСИМУМ).
Кроме того, обход выборки с несколькими уровнями группировок должен строиться каскадно: каждый следующий уровень необходимо запрашивать из выборки предыдущего уровня, а не из исходного объекта РезультатЗапроса.
Разберем правильный алгоритм многоуровневого обхода выборки:
// Получаем выборку верхнего уровня по торговому агенту
ВыборкаАгент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Менеджер");
Пока ВыборкаАгент.Следующий() Цикл
// Выводим строку итогов по агенту
// Доступны поле ВыборкаАгент.Менеджер и агрегаты СУММА(...)
// Получаем выборку второго уровня из текущей строки агента
ВыборкаКонтрагент = ВыборкаАгент.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Контрагент");
Пока ВыборкаКонтрагент.Следующий() Цикл
// Выводим строку итогов по контрагенту
// Получаем детальные записи по документам
ВыборкаДетали = ВыборкаКонтрагент.Выбрать(ОбходРезультатаЗапроса.Прямой);
Пока ВыборкаДетали.Следующий() Цикл
// Выводим детальные поля: документ реализации, дата, оплата
КонецЦикла;
КонецЦикла;
КонецЦикла;
При проверке типа текущей записи в смешанных выборках анализируем системное свойство Выборка.ТипЗаписи с помощью системного перечисления ТипЗаписиЗапроса (значения ИтогПоГруппировке, ДетальнаяЗапись, ОбщийИтог).
Для вывода иерархических отчетов с промежуточными итогами по агентам и контрагентам оптимально применять СКД. В схеме компоновки данных достаточно передать плоский запрос с детальными полями без блока ИТОГИ. Система компоновки данных автоматически рассчитывает ресурсы на нужных уровнях группировок, исключает дублирование строк при выводе в табличный документ и корректно сворачивает показатели задолженности.