Как правильно реализовать условие «Если... Тогда» в секции ГДЕ запроса 1С?

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

При разработке отчетов и запросов часто возникает задача: применить фильтр только в том случае, если пользователь установил определенный параметр (флаг). Например, если флажок &БезДопРасходов установлен в значение ИСТИНА, мы должны отфильтровать записи по конкретному типу документа, а если флажок снят — вывести все записи без ограничений. Разберем, как реализовать такую логику правильно, красиво и с соблюдением стандартов производительности.

Метод 1. Использование конструкции ВЫБОР КОГДА

Рассмотрим первый вариант, к которому часто прибегают начинающие разработчики. Логика проста: внутри секции ГДЕ мы пытаемся построить ветвление. Однако стоит помнить, что результатом конструкции ВЫБОР в секции ГДЕ должно быть логическое выражение (Булево).

Проанализируем пример «красивого», но функционального кода:


ГДЕ
    ВЫБОР
        КОГДА &БезДопРасходов
            ТОГДА ЗакупкиОбороты.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг
        ИНАЧЕ ИСТИНА
    КОНЕЦ

В этом примере, если параметр &БезДопРасходов равен ИСТИНА, запрос проверяет тип регистратора. Если же параметр равен ЛОЖЬ, условие превращается в ГДЕ ИСТИНА, что позволяет выбрать все строки. Это гораздо чище, чем использование технических заглушек вида 0 = 0.

Метод 2. Логические операторы ИЛИ и НЕ

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

  1. Если параметр &БезДопРасходов равен ЛОЖЬ, то первая часть условия (НЕ &БезДопРасходов) становится ИСТИНА.
  2. По правилам логики ИЛИ, если первая часть истинна, все выражение становится истинным, и вторая часть (фильтр по ссылке) не влияет на результат.
  3. Если параметр &БезДопРасходов равен ИСТИНА, то первая часть ложна, и СУБД вынуждена проверять вторую часть условия.

Посмотрим на пример реализации:


ГДЕ
    (НЕ &БезДопРасходов)
    ИЛИ ЗакупкиОбороты.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

Этот подход лаконичен и эффективно решает задачу в обычных запросах. Однако у него есть скрытая проблема — производительность.

Почему ССЫЛКА лучше, чем ТИПЗНАЧЕНИЯ?

В обсуждении часто всплывает вопрос выбора между ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.ПоступлениеТоваровУслуг) и оператором ССЫЛКА. Проанализируем ситуацию с точки зрения работы СУБД:

Оператор ССЫЛКА — это специализированный инструмент платформы 1С. На уровне SQL он транслируется в простую проверку идентификатора типа (номера таблицы), который хранится прямо в поле составного типа. Это происходит мгновенно.

Функция ТИПЗНАЧЕНИЯ является более тяжелой. В некоторых сложных сценариях (особенно при работе с очень длинными составами типов) она может порождать избыточные соединения с системными таблицами метаданных. Поэтому всегда используйте ССЫЛКА, когда нужно проверить принадлежность к одному конкретному типу.

Метод 3. Профессиональный подход в СКД (Фигурные скобки)

Если вы разрабатываете отчет в Системе компоновки данных (СКД), то использование ВЫБОР или ИЛИ в тексте запроса — не самый лучший путь. СКД обладает механизмом расширения языка запросов, который позволяет делать условия по-настоящему динамическими.

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

Правильнее использовать необязательные условия в фигурных скобках:


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

Как это работает? Мы не привязываемся к параметру &БезДопРасходов напрямую в тексте. Вместо этого мы описываем потенциально возможное условие. Теперь в настройках СКД на закладке «Параметры» или «Отбор» мы можем управлять этим фильтром. Если пользователь (или вы программно) не активирует этот отбор, СКД вообще не включит секцию ГДЕ в итоговый SQL-запрос. Это гарантирует максимальную скорость работы.

Нюансы работы с NULL

Проанализируем ситуацию, когда поле, по которому идет фильтрация, может содержать NULL (например, при левом соединении). В 1С (как и в SQL) результат сравнения NULL с чем-либо дает UNKNOWN (в 1С трактуется как ЛОЖЬ).

Если вы используете конструкцию: ГДЕ (НЕ &Флаг) ИЛИ Поле ССЫЛКА Тип и поле равно NULL, а флаг установлен (ИСТИНА), то результат всего условия будет ЛОЖЬ. Запись будет отфильтрована. Если это не то, что вам нужно, не забывайте обрабатывать NULL с помощью функции ЕСТЬNULL().

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

Для создания качественного кода придерживайтесь следующих правил:

Соблюдение этих рекомендаций не только сделает ваш код «красивым», но и обеспечит его стабильную работу при росте объема данных в информационной базе.

← На главную