При разработке отчетов в системе компоновки данных (СКД) часто возникает задача: предоставить пользователю возможность формировать отчет как по конкретному контрагенту, так и по всем контрагентам сразу (без фильтрации), если поле отбора оставлено пустым. Если написать жесткое условие в секции ГДЕ, платформа выдаст ошибку «Не задано значение параметра» при незаполненном значении. Разберем подробно, почему возникает такая ошибка и какими способами можно реализовать гибкую фильтрацию.
Основным и наиболее правильным механизмом в СКД является использование конструкций расширения языка запросов, которые заключаются в фигурные скобки {}. Когда условие помещено в фигурные скобки, компоновщик данных анализирует настройки отчета: если параметр или поле отбора заполнено пользователем, условие автоматически добавляется в итоговый SQL-запрос, а если не заполнено — условие полностью вырезается из текста запроса.
Посмотрим на пример запроса к виртуальной таблице регистра бухгалтерии:
ВЫБРАТЬ
ХозрасчетныйОстаткиИОбороты.Субконто3.ДоговорКонтрагента КАК Договор,
ХозрасчетныйОстаткиИОбороты.Субконто2 КАК Материал,
ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстатокДт КАК ОстатокНаНачало,
ХозрасчетныйОстаткиИОбороты.СуммаОборотДт КАК Приход,
ХозрасчетныйОстаткиИОбороты.СуммаОборотКт КАК Расход,
ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт КАК ОстатокНаКонец
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
,
,
Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.МатериалыПереданныеВПереработку),
,
) КАК ХозрасчетныйОстаткиИОбороты
{ГДЕ
ХозрасчетныйОстаткиИОбороты.Субконто1 = &Контрагент}
Разберем по шагам, как правильно настроить параметры в схеме компоновки данных, чтобы избежать ошибки «Не задано значение параметра»:
&Контрагент.Вместо жесткой привязки к параметру &Контрагент можно описать поле отбора в фигурных скобках с использованием конструкции .*. Это дает пользователю возможность использовать не только точное равенство, но и сложные виды сравнения (например, В списке, В группе, Не равно):
ВЫБРАТЬ
ХозрасчетныйОстаткиИОбороты.Субконто3.ДоговорКонтрагента КАК Договор,
ХозрасчетныйОстаткиИОбороты.Субконто2 КАК Материал,
ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстатокДт КАК ОстатокНаНачало,
ХозрасчетныйОстаткиИОбороты.СуммаОборотДт КАК Приход,
ХозрасчетныйОстаткиИОбороты.СуммаОборотКт КАК Расход,
ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт КАК ОстатокНаКонец
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
,
,
Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.МатериалыПереданныеВПереработку),
,
) КАК ХозрасчетныйОстаткиИОбороты
{ГДЕ
ХозрасчетныйОстаткиИОбороты.Субконто1.* КАК Контрагент}
В этом случае отбор настраивается на вкладке «Настройки» в разделе «Отбор». Если пользователь снимает галочку с отбора по контрагенту или оставляет поле пустым, СКД автоматически исключает фильтр из запроса, и формируется отчет со всеми данными.
Проанализируем еще один подход, предложенный на форуме, — обработку условия через конструкцию ВЫБОР КОГДА прямо в секции ГДЕ без использования синтаксиса СКД:
ГДЕ
ВЫБОР
КОГДА &Контрагент ЕСТЬ NULL
ИЛИ &Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
ТОГДА ИСТИНА
ИНАЧЕ ХозрасчетныйОстаткиИОбороты.Субконто1 = &Контрагент
КОНЕЦ
Рассмотрим подробнее особенности этого метода:
ИЛИ и ВЫБОР в условиях соединения и фильтрации. Это приводит к полному сканированию таблицы итогов (Table Scan / Index Scan) вместо быстрого точечного поиска (Index Seek).Выясним причину, по которой фильтрацию по субконто лучше передавать в параметры самой виртуальной таблицы:
Когда условие накладывается в секции ГДЕ после имени виртуальной таблицы, платформа сначала рассчитывает итоги по всем записям регистра за указанный период и только потом применяет фильтрацию к готовой выборке. Чтобы запрос выполнялся максимально быстро, условия по субконто следует помещать непосредственно в параметры виртуальной таблицы ОстаткиИОбороты в секцию условий субконто, также обрамляя их в фигурные скобки СКД.