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

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

В практике разработки на платформе 1С часто возникает задача: необходимо построить отчет или выборку данных так, чтобы фильтр по конкретному полю (например, Контрагент или Организация) применялся только в том случае, если пользователь выбрал соответствующее значение на форме. Если же значение не выбрано, отчет должен выводить данные по всем объектам без ограничений.

В рамках этой статьи мы подробно разберем несколько проверенных методов решения этой задачи — от простых логических выражений внутри запроса до профессионального использования Системы компоновки данных (СКД).

Метод 1. Использование логического оператора «ИЛИ»

Это один из самых популярных и простых способов. Его суть заключается в том, чтобы создать условие, которое будет истинным либо при совпадении значения, либо при пустом параметре. Рассмотрим, как это выглядит в тексте запроса.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Продажи.Контрагент,
    |   Продажи.СуммаОборот
    |ИЗ
    |   РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК Продажи
    |ГДЕ
    |   (НЕ &ИспользоватьОтбор ИЛИ Продажи.Контрагент = &Контрагент)";

Запрос.УстановитьПараметр("Контрагент", Контрагент);
Запрос.УстановитьПараметр("ИспользоватьОтбор", ЗначениеЗаполнено(Контрагент));
Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецПериода);

Важное замечание по производительности: Несмотря на простоту, использование оператора ИЛИ в блоке ГДЕ может привести к замедлению выполнения запроса на больших объемах данных. Это связано с тем, что СУБД (например, SQL Server) не всегда может эффективно использовать индексы при наличии условий с ИЛИ. Вместо быстрого поиска по индексу (Index Seek) система может переключиться на полное сканирование таблицы.

Метод 2. Конструкция «ВЫБОР КОГДА...» в тексте запроса

Если мы хотим обойтись одним параметром и проверить его на «пустоту» прямо внутри SQL-запроса, можно использовать конструкцию ВЫБОР. Посмотрим на реализацию этого подхода:


ГДЕ
    ВЫБОР 
        КОГДА &Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) 
            ТОГДА Контрагент = &Контрагент 
        ИНАЧЕ ИСТИНА 
    КОНЕЦ

Здесь система сначала проверяет, является ли переданный параметр пустой ссылкой. Если ссылка не пустая, применяется фильтр по контрагенту. В противном случае условие превращается в ИСТИНА, что позволяет выбрать все записи. Этот метод часто используется в виртуальных таблицах, где условия прописываются в параметрах самой таблицы.

Метод 3. Динамическое формирование текста запроса

Рассмотрим ситуацию, когда нам нужно максимально оптимизировать запрос. Самый «чистый» способ с точки зрения SQL — это вообще не включать условие в текст, если оно не требуется. Для этого мы можем использовать простую склейку строк или замену меток.

Разберем пример с использованием замены текста:


ТекстУсловия = "";
Если ЗначениеЗаполнено(Контрагент) Тогда
    ТекстУсловия = "И Контрагент = &Контрагент";
КонецЕсли;

Запрос.Текст = 
    "ВЫБРАТЬ * ИЗ РегистрНакопления.Взаиморасчеты.ОстаткиИОбороты(&Нач, &Кон, , , " + ТекстУсловия + ")";

Однако более профессионально использовать объект СхемаЗапроса или специальные метки-комментарии. Посмотрим на пример с меткой:


ТекстЗапроса = 
    "ВЫБРАТЬ * ИЗ Справочник.Номенклатура КАК Номенклатура
    | //ГДЕ_УСЛОВИЕ";

Если ЗначениеЗаполнено(ВыбраннаяГруппа) Тогда
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "//ГДЕ_УСЛОВИЕ", "ГДЕ Родитель = &Родитель");
    Запрос.УстановитьПараметр("Родитель", ВыбраннаяГруппа);
Иначе
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "//ГДЕ_УСЛОВИЕ", "");
КонецЕсли;

Метод 4. Использование Построителя запроса или СКД (фигурные скобки)

В системе 1С 8 существует мощный механизм, называемый «Построитель» (в обычных формах) или «Система компоновки данных» (СКД). Эти механизмы позволяют использовать расширенный синтаксис запросов с фигурными скобками {}.

Проанализируем, как это работает. Если условие заключено в фигурные скобки, оно становится «необязательным». Если параметр, указанный внутри скобок, не будет установлен в настройках компоновки или построителя, платформа 1С автоматически удалит это условие из итогового SQL-запроса перед отправкой на сервер базы данных.

Пример синтаксиса в СКД:


ВЫБРАТЬ
    Продажи.Контрагент,
    Продажи.Сумма
ИЗ
    РегистрНакопления.Продажи КАК Продажи
{ГДЕ
    (Продажи.Контрагент = &Контрагент)}

В этом случае программисту не нужно писать код проверки Если ЗначениеЗаполнено(). Достаточно того, что поле выведено в список доступных отборов. Если пользователь на форме отчета не установил галочку напротив контрагента, условие будет проигнорировано автоматически. Это самый правильный метод с точки зрения архитектуры 1С и производительности СУБД.

Метод 5. Использование оператора «В» для списков

Иногда требуется передать не одного контрагента, а целый список. Выясним причину, почему обычное равенство здесь не подойдет. Если мы используем Контрагент В (&СписокКонтрагентов), и список пуст, запрос может вернуть пустой результат, а не все записи.

Чтобы решить эту проблему, мы можем использовать комбинацию методов:

  1. Проверяем количество элементов в списке перед выполнением запроса.
  2. Если список пуст, либо не устанавливаем параметр (используя метод СКД), либо передаем флаг «ОтборВключен = Ложь».
  3. В самом запросе используем конструкцию: ГДЕ (НЕ &ОтборПоСпискуВключен ИЛИ Контрагент В (&СписокКонтрагентов)).

Подведение итогов и рекомендации

Мы рассмотрели различные подходы к решению задачи переменного условия в запросе. Выбор метода зависит от контекста разработки:

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

← На главную