Как исключить записи на основе временной таблицы в запросе 1С

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

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

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

Выясним причину проблемы и ограничения платформы

В языке запросов 1С конструкция В (&Параметр) предназначена исключительно для работы с параметрами, которые передаются из встроенного языка (например, массивы, списки значений или таблицы значений). Передать имя временной таблицы, созданной внутри пакета запросов с помощью ключевого слова ПОМЕСТИТЬ, в качестве параметра &Имя невозможно — платформа не поддерживает обращение к временным таблицам через синтаксис параметров.

Сформулируем основные способы решения этой задачи, которые работают корректно и эффективно.

Способ 1. Использование левого соединения и условия ЕСТЬ NULL

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

Разберем пример реализации этого подхода по шагам:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    АР_ЗаключениеДоговораАренды.Кос_НомерСтарогоДоговора КАК НомерДоговора
ПОМЕСТИТЬ ЮляВТ_СтарыеНомераДоговора
ИЗ
    Документ.АР_ЗаключениеДоговораАренды КАК АР_ЗаключениеДоговораАренды
ГДЕ
    АР_ЗаключениеДоговораАренды.Дата >= &НачалоПериода
ИНДЕКСИРОВАТЬ ПО
    НомерДоговора
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗаключениеДоговора.Ссылка КАК Договор,
    ЗаключениеДоговора.Номер КАК Номер
ИЗ
    РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
    ЛЕВОЕ СОЕДИНЕНИЕ ЮляВТ_СтарыеНомераДоговора КАК СтарыеНомера
    ПО ЗаключениеДоговора.Номер = СтарыеНомера.НомерДоговора
ГДЕ
    СтарыеНомера.НомерДоговора ЕСТЬ NULL

Проанализируем этот запрос: если в основной таблице запись имеет номер, которого нет во временной таблице ЮляВТ_СтарыеНомераДоговора, то при левом соединении поля временной таблицы будут содержать значение NULL. Условие ЕСТЬ NULL оставляет в выборке только те строки, которых не оказалось во временной таблице.

Способ 2. Использование подзапроса с оператором НЕ В

Если требуется сохранить наглядность исходного условия отбора, вместо обращения к параметру можно выбрать данные из временной таблицы с помощью вложенного запроса.

Посмотрим на пример такого запроса:


ВЫБРАТЬ
    ЗаключениеДоговора.Ссылка КАК Договор,
    ЗаключениеДоговора.Номер КАК Номер
ИЗ
    РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
ГДЕ
    НЕ ЗаключениеДоговора.Номер В
        (ВЫБРАТЬ
            ВТ.НомерДоговора
        ИЗ
            ЮляВТ_СтарыеНомераДоговора КАК ВТ
        ГДЕ
            ВТ.НомерДоговора ЕСТЬ НЕ NULL)

Обратите внимание: при использовании конструкции НЕ В обязательно добавляйте условие ГДЕ Поле ЕСТЬ НЕ NULL во вложенном запросе. Если во временной таблице окажется хотя бы одно значение NULL, трехзначная логика SQL приведет к тому, что весь итоговый запрос вернет пустой результат.

Способ 3. Использование конструкции НЕ СУЩЕСТВУЕТ (NOT EXISTS)

Альтернативным вариантом проверки отсутствия записей является использование ключевых слов НЕ СУЩЕСТВУЕТ. Данная конструкция проверяет корреляцию между основной и временной таблицами.

Рассмотрим структуру данного запроса:


ВЫБРАТЬ
    ЗаключениеДоговора.Ссылка КАК Договор,
    ЗаключениеДоговора.Номер КАК Номер
ИЗ
    РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
ГДЕ
    НЕ СУЩЕСТВУЕТ
        (ВЫБРАТЬ
            1
        ИЗ
            ЮляВТ_СтарыеНомераДоговора КАК ВТ
        ГДЕ
            ВТ.НомерДоговора = ЗаключениеДоговора.Номер)

Рекомендации по повышению производительности

При работе с временными таблицами в 1С следует соблюдать несколько важных правил оптимизации:

  1. Индексация ключевых полей: всегда индексируйте поля временной таблицы, по которым выполняется соединение или проверка во вложенном запросе (указывайте ИНДЕКСИРОВАТЬ ПО ... при создании таблицы). Это исключает полное сканирование таблицы СУБД при вычислении связей.
  2. Область видимости в СКД: помните, что временные таблицы, созданные в одном наборе данных СКД, недоступны в других наборах данных. Весь цикл работы с временной таблицей должен располагаться строго в рамках единого пакета запросов одного набора данных.
← На главную