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