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