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