При работе с языком запросов 1С и Схемой компоновки данных (СКД) разработчики часто сталкиваются с задачей исключить из итогового результата записи, присутствующие во временной таблице. Обычный синтаксис передачи параметра через символ амперсанда &ИмяПараметра в этом случае не работает, вызывая синтаксическую ошибку.
Рассмотрим подробнее причины возникшей проблемы и проанализируем различные варианты её правильного решения.
В языке запросов 1С конструкция В (&Параметр) предназначена исключительно для работы с параметрами, которые передаются из встроенного языка (например, массивы, списки значений или таблицы значений). Передать имя временной таблицы, созданной внутри пакета запросов с помощью ключевого слова ПОМЕСТИТЬ, в качестве параметра &Имя невозможно — платформа не поддерживает обращение к временным таблицам через синтаксис параметров.
Сформулируем основные способы решения этой задачи, которые работают корректно и эффективно.
Это один из наиболее распространенных способов исключения записей. Мы связываем временную таблицу с основной с помощью левого соединения и устанавливаем условие отбора на отсутствие совпадающих строк.
Разберем пример реализации этого подхода по шагам:
ВЫБРАТЬ РАЗЛИЧНЫЕ
АР_ЗаключениеДоговораАренды.Кос_НомерСтарогоДоговора КАК НомерДоговора
ПОМЕСТИТЬ ЮляВТ_СтарыеНомераДоговора
ИЗ
Документ.АР_ЗаключениеДоговораАренды КАК АР_ЗаключениеДоговораАренды
ГДЕ
АР_ЗаключениеДоговораАренды.Дата >= &НачалоПериода
ИНДЕКСИРОВАТЬ ПО
НомерДоговора
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЗаключениеДоговора.Ссылка КАК Договор,
ЗаключениеДоговора.Номер КАК Номер
ИЗ
РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
ЛЕВОЕ СОЕДИНЕНИЕ ЮляВТ_СтарыеНомераДоговора КАК СтарыеНомера
ПО ЗаключениеДоговора.Номер = СтарыеНомера.НомерДоговора
ГДЕ
СтарыеНомера.НомерДоговора ЕСТЬ NULL
Проанализируем этот запрос: если в основной таблице запись имеет номер, которого нет во временной таблице ЮляВТ_СтарыеНомераДоговора, то при левом соединении поля временной таблицы будут содержать значение NULL. Условие ЕСТЬ NULL оставляет в выборке только те строки, которых не оказалось во временной таблице.
Если требуется сохранить наглядность исходного условия отбора, вместо обращения к параметру можно выбрать данные из временной таблицы с помощью вложенного запроса.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
ЗаключениеДоговора.Ссылка КАК Договор,
ЗаключениеДоговора.Номер КАК Номер
ИЗ
РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
ГДЕ
НЕ ЗаключениеДоговора.Номер В
(ВЫБРАТЬ
ВТ.НомерДоговора
ИЗ
ЮляВТ_СтарыеНомераДоговора КАК ВТ
ГДЕ
ВТ.НомерДоговора ЕСТЬ НЕ NULL)
Обратите внимание: при использовании конструкции НЕ В обязательно добавляйте условие ГДЕ Поле ЕСТЬ НЕ NULL во вложенном запросе. Если во временной таблице окажется хотя бы одно значение NULL, трехзначная логика SQL приведет к тому, что весь итоговый запрос вернет пустой результат.
Альтернативным вариантом проверки отсутствия записей является использование ключевых слов НЕ СУЩЕСТВУЕТ. Данная конструкция проверяет корреляцию между основной и временной таблицами.
Рассмотрим структуру данного запроса:
ВЫБРАТЬ
ЗаключениеДоговора.Ссылка КАК Договор,
ЗаключениеДоговора.Номер КАК Номер
ИЗ
РегистрСведений.ЗаключениеДоговора КАК ЗаключениеДоговора
ГДЕ
НЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ
1
ИЗ
ЮляВТ_СтарыеНомераДоговора КАК ВТ
ГДЕ
ВТ.НомерДоговора = ЗаключениеДоговора.Номер)
При работе с временными таблицами в 1С следует соблюдать несколько важных правил оптимизации:
ИНДЕКСИРОВАТЬ ПО ... при создании таблицы). Это исключает полное сканирование таблицы СУБД при вычислении связей.