Почему конструкция ВЫБОР КОГДА в запросах 1С работает некорректно при проверке табличных частей?

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

Часто при разработке отчетов или настройке механизмов доступа к данным мы сталкиваемся с необходимостью фильтровать выборку документов по условиям, связанным с их табличными частями. Нередко программисты выбирают путь наименьшего сопротивления, используя конструкцию ВЫБОР КОГДА прямо в секции ГДЕ. Однако, как показывает практика, это приводит к непредсказуемым результатам, дублированию строк или игнорированию части условий фильтрации. Давайте разберем, почему это происходит и как правильно строить такие запросы.

В чем заключается проблема?

Основная причина заключается в том, как платформа 1С транслирует запросы 1С в SQL-запросы к базе данных. Когда мы обращаемся к табличной части (ТЧ) внутри секции ГДЕ, 1С пытается выполнить неявное соединение. Если при этом внутри ВЫБОР смешиваются обычные реквизиты документа и данные из вложенной таблицы, оптимизатор СУБД может построить план выполнения, который приводит к декартовому произведению или некорректному объединению множеств.

Рассмотрим пример, который вызывает вопросы:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка
ИЗ
    Документ.Док КАК Док
ГДЕ
    ВЫБОР
        КОГДА &ТекущийПользователь = Док.ААА ТОГДА ИСТИНА
        КОГДА &ТекущийПользователь В (Док.ТЧ_ААА.ААА) ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ

При таком подходе платформа может «неправильно раскрутить» условие, что приведет к возврату лишних записей. В ряде случаев, особенно при работе с большими объемами данных, этот код может работать нестабильно в зависимости от используемой СУБД (MS SQL, PostgreSQL или файловая версия).

Способ №1: Использование логического ИЛИ

Самый простой и понятный способ избежать «магии» платформы — отказаться от ВЫБОР в пользу стандартных логических операторов. Вместо сложной конструкции мы можем явно описать условия поиска.

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


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка
ИЗ
    Документ.Док КАК Док
ГДЕ
    &ТекущийПользователь = Док.ААА 
    ИЛИ &ТекущийПользователь В (ВЫБРАТЬ ДокТЧ.ААА ИЗ Документ.Док.ТЧ_ААА КАК ДокТЧ ГДЕ ДокТЧ.Ссылка = Док.Ссылка)

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

Способ №2: Явное соединение (JOIN)

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

Посмотрим на пример реализации через ЛЕВОЕ СОЕДИНЕНИЕ:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка
ИЗ
    Документ.Док КАК Док
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.Док.ТЧ_ААА КАК ДокААА
        ПО Док.Ссылка = ДокААА.Ссылка
            И (ДокААА.ААА = &ТекущийПользователь)
ГДЕ
    Док.ААА = &ТекущийПользователь
    ИЛИ ДокААА.Ссылка ЕСТЬ НЕ NULL

Преимущества данного метода:

  1. Вы явно видите, какие данные присоединяются к основному документу.
  2. Проверка на ЕСТЬ НЕ NULL позволяет точно определить, нашлась ли запись в табличной части, соответствующая критерию.
  3. Такой запрос проще отлаживать, так как логика соединения четко отделена от условий фильтрации.

Способ №3: Использование регистра сведений

Если задача заключается в организации прав доступа (RLS) или фильтрации по сложным связям, которые меняются достаточно часто, самым эффективным решением будет создание отдельного РегистраСведений. В этом регистре можно хранить записи вида «Документ — Пользователь».

Почему это надежно:

Подводя итог

Работа с табличными частями требует осторожности. Мы выяснили, что использование ВЫБОР КОГДА в фильтрах запросов — это «моветон», который может привести к ошибкам в логике работы программы. Мы рекомендуем:

  1. Всегда отдавать предпочтение явным соединениям ЛЕВОЕ СОЕДИНЕНИЕ, если нужно проверить наличие записи в ТЧ.
  2. Использовать логические конструкции ИЛИ для простых условий.
  3. Для сложных или высоконагруженных систем переносить логику связей в РегистрыСведений.

Проанализировав эти методы, вы сможете писать более надежный, производительный и, главное, предсказуемый код на 1С, который будет одинаково успешно работать на любой версии платформы и СУБД.

← На главную