Перейти к содержимому

7.6 Вложенный запрос может использоваться

Опубликовано: Обновлено:

Telegram → Просто о платформе 1С

❓ 7.6 Вложенный запрос может использоваться:


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

Вложенные запросы позволяют сначала сформировать необходимые данные, а затем использовать их в другом запросе.

Где может использоваться вложенный запрос

Заголовок раздела «Где может использоваться вложенный запрос»

Вложенный запрос может участвовать в запросе несколькими способами.

Результат вложенного запроса может выступать источником данных внешнего запроса:

ВЫБРАТЬ
Продажи.Номенклатура,
Продажи.Количество
ИЗ
(ВЫБРАТЬ
РеализацияТовары.Номенклатура КАК Номенклатура,
СУММА(РеализацияТовары.Количество) КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
СГРУППИРОВАТЬ ПО
РеализацияТовары.Номенклатура) КАК Продажи

Здесь результат вложенного запроса получает имя Продажи и становится источником данных внешнего запроса.

Результат вложенного запроса может участвовать в соединении с другим источником:

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

Здесь вложенный запрос Продажи является одной из соединяемых выборок.

Вложенный запрос может использоваться в условии отбора, например с оператором В:

ВЫБРАТЬ
Товары.Ссылка
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Ссылка В
(ВЫБРАТЬ
Остатки.Номенклатура
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки() КАК Остатки)

Вложенный запрос формирует множество значений, которое используется внешним запросом при проверке условия В.

Вложенный запрос может находиться непосредственно в условии соединения:

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены КАК Цены
ПО Цены.Номенклатура = Товары.Номенклатура
И Цены.Период В
(ВЫБРАТЬ
МАКСИМУМ(ПредыдущиеЦены.Период)
ИЗ
РегистрСведений.Цены КАК ПредыдущиеЦены
ГДЕ
ПредыдущиеЦены.Номенклатура = Товары.Номенклатура)

Здесь вложенный запрос не является отдельным источником соединения — он входит непосредственно в выражение ПО.

Вложенный запрос может использоваться в выражении, передаваемом в параметры виртуальной таблицы.

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

РегистрНакопления.ТоварыНаСкладах.Остатки(
,
Номенклатура В
(ВЫБРАТЬ
Товары.Номенклатура
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары)
)

В этом случае вложенный запрос является частью условия, передаваемого в параметр виртуальной таблицы.

Вложенные запросы и временные таблицы позволяют решать похожую задачу — получать промежуточные данные для дальнейшей обработки. Но механизм их использования различается.

Вложенный запросВременная таблица
Находится внутри другого запросаПромежуточный результат помещается во временную таблицу
Результат используется непосредственно во внешнем запросеВременную таблицу можно использовать в последующих запросах
Отдельная индексация промежуточного результата не задаетсяДля временной таблицы можно задать индекс с помощью ИНДЕКСИРОВАТЬ ПО

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


Возможность использовать вложенный запрос в определенной конструкции языка запросов не означает, что эта конструкция рекомендуется с точки зрения производительности.

Для некоторых случаев стандарты разработки 1С содержат отдельные ограничения.

📐 Стандарт «Ограничения на соединения с вложенными запросами и виртуальными таблицами» — #std655:

Речь идет о конструкции, в которой результат вложенного запроса является одной из соединяемых выборок:

ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ
(ВЫБРАТЬ
...
) КАК Продажи
ПО Номенклатура.Ссылка = Продажи.Номенклатура

Для выбора способа соединения оптимизатору СУБД необходимо оценить количество записей в соединяемых выборках.

Для физических таблиц СУБД может использовать имеющуюся статистику. Оценить количество записей, которое вернет вложенный запрос, может быть сложнее.

Физическая таблица
        ↓
СУБД может оценить объем выборки
на основании имеющейся статистики
        ↓
Проще выбрать способ соединения

Вложенный запрос
        ↓
Количество возвращаемых записей
оценить сложнее
        ↓
Оптимизатор может ошибиться
при выборе способа соединения
        ↓
Возможен неоптимальный план выполнения

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

📐Стандарт «Ограничения на использование вложенных запросов в условии соединения» — #std656:

Здесь ситуация другая: соединяемым источником является обычная таблица, но вложенный запрос находится непосредственно в условии ПО:

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены КАК Цены
ПО Цены.Номенклатура = Товары.Номенклатура
И Цены.Период В
(ВЫБРАТЬ
...
)

Стандарт рекомендует не использовать вложенные запросы в условиях соединения. Такая конструкция может привести к значительному замедлению выполнения запроса, а в отдельных случаях — к его неработоспособности на некоторых СУБД.

Для таких случаев запрос рекомендуется переписать с использованием временных таблиц.

#std655
Вложенный запрос — источник соединения

СОЕДИНЕНИЕ
    (ВЫБРАТЬ ...) КАК Данные
ПО ...


#std656
Вложенный запрос — внутри условия соединения

СОЕДИНЕНИЕ Таблица
ПО Поле В
    (ВЫБРАТЬ ...)

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


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

При этом возможность использовать вложенный запрос нужно отличать от рекомендаций по производительности: стандарты разработки отдельно ограничивают соединения с вложенными запросами (#std655) и использование вложенных запросов в условиях соединения (#std656).