Как в запросе 1С сделать условие необязательным?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок часто возникает задача: применить фильтр в запросе только в том случае, если пользователь установил соответствующий флаг или выбрал значение. Если же условие не задано, запрос должен вернуть все записи без учета этого фильтра. Разберем несколько способов решения этой задачи, начиная от простых логических выражений внутри запроса и заканчивая программным формированием текста.

Способ 1. Использование логического оператора «ИЛИ» в параметрах

Это один из самых распространенных и простых методов. Мы передаем в запрос дополнительный булевый параметр, который определяет, нужно ли применять фильтр. Проанализируем пример кода запроса:


"ВЫБРАТЬ
|    СервисыКонтрагентов.Контрагент,
|    СервисыКонтрагентов.Период
|ИЗ
|    РегистрСведений.СервисыКонтрагентов КАК СервисыКонтрагентов
|ГДЕ
|    СервисыКонтрагентов.Период МЕЖДУ &Период1 И &Период2
|    И (СервисыКонтрагентов.Контрагент = &Контрагент ИЛИ &ОтборПоКонтрагентуЛожь)"

В данном случае, если параметр &ОтборПоКонтрагентуЛожь будет иметь значение Истина, то все выражение в скобках станет истинным для каждой строки, и фильтр по контрагенту фактически перестанет работать. Если же параметр равен Ложь, запрос будет учитывать равенство контрагента.

Важно: При использовании этого метода нужно следить за типами. Если в параметр &Контрагент передать Неопределено, это может повлиять на производительность в некоторых СУБД из-за особенностей оптимизации планов запросов.

Способ 2. Программная сборка текста запроса

Если условий много или запрос очень сложный, лучше всего формировать текст запроса динамически в коде на встроенном языке. Рассмотрим, как это реализовать:


ТекстЗапроса = 
"ВЫБРАТЬ
|    СервисыКонтрагентов.Контрагент,
|    СервисыКонтрагентов.Период
|ИЗ
|    РегистрСведений.СервисыКонтрагентов КАК СервисыКонтрагентов
|ГДЕ
|    СервисыКонтрагентов.Период МЕЖДУ &Период1 И &Период2";

Если ЗначениеЗаполнено(Контрагент) Тогда
    ТекстЗапроса = ТекстЗапроса + "
    |    И СервисыКонтрагентов.Контрагент = &Контрагент";
КонецЕсли;

Запрос.Текст = ТекстЗапроса;

Преимущество этого метода заключается в том, что в итоговый SQL-запрос попадают только необходимые условия. Это положительно сказывается на SARGability (способности СУБД эффективно использовать индексы). Лишние логические конструкции «ИЛИ» не будут мешать оптимизатору базы данных строить правильный план выполнения.

Способ 3. Использование конструкции «ВЫБОР»

Еще один вариант реализации логики внутри самого запроса — использование оператора ВЫБОР. Проанализируем ситуацию, когда нам нужно программно управлять фильтром через параметр:


"ГДЕ
|    СервисыКонтрагентов.Период МЕЖДУ &Период1 И &Период2
|    И ВЫБОР 
|        КОГДА &ИгнорироватьКонтрагента ТОГДА ИСТИНА 
|        ИНАЧЕ СервисыКонтрагентов.Контрагент = &Контрагент 
|    КОНЕЦ"

Здесь логика аналогична первому способу, но для некоторых разработчиков она выглядит более наглядной.

Способ 4. Механизмы Системы компоновки данных (СКД)

Если вы разрабатываете отчет, наиболее правильным и современным подходом будет использование Системы компоновки данных. В СКД можно использовать фигурные скобки {} для описания необязательных условий. Разберем пример:


"ВЫБРАТЬ
|    СервисыКонтрагентов.Контрагент,
|    СервисыКонтрагентов.Период
|ИЗ
|    РегистрСведений.СервисыКонтрагентов КАК СервисыКонтрагентов
|ГДЕ
|    СервисыКонтрагентов.Период МЕЖДУ &Период1 И &Период2
|    {ГДЕ СервисыКонтрагентов.Контрагент.* КАК Контрагент}"

При таком подходе платформа 1С сама добавит условие в итоговый запрос, только если пользователь установит соответствующий отбор в настройках отчета. Это избавляет программиста от ручного анализа заполненности параметров.

Особенности работы с виртуальными таблицами

Выясним причину, по которой условия в секции ГДЕ для виртуальных таблиц (например, ОстаткиИОбороты или СрезПоследних) работают медленно. Если вы используете динамическое условие для таких таблиц, старайтесь передавать его в параметры виртуальной таблицы, а не в общее условие ГДЕ.

Однако параметры виртуальной таблицы нельзя сделать необязательными простым способом «ИЛИ». В таких случаях программная сборка текста запроса (Способ 2) является единственным верным решением для обеспечения высокой производительности.

Продвинутый метод: Объект «СхемаЗапроса»

Для динамического управления структурой запроса в сложных подсистемах можно использовать объект СхемаЗапроса. Он позволяет программно манипулировать коллекцией Отбор, добавлять или удалять условия как объекты, не работая напрямую со строками. Это помогает избежать синтаксических ошибок, которые часто случаются при простой склейке строк через СтрЗаменить.

Подведем итог: для простых задач на формах подойдет условие с ИЛИ, для сложных и высоконагруженных участков кода — программная сборка текста, а для отчетов — использование механизмов отборов СКД.

← На главную