Вложенный запрос – это запрос, который вложен в другой запрос. Синтаксически выглядит, как запрос, заключенный в круглые скобки. Ему присваивается псевдоним. Как правило, используется для получения отборов, группировок и агрегатных функций с последующим соединением в запросе верхнего уровня, также в операторах «В», «ИЗ», «ГДЕ» и других.
Рассмотрим примеры вложенного запроса. В следующем запросе показано, как найти пять партий поступлений товара с максимальным количеством покупки выбранных наименований в заданном периоде и по какому документу, и в каком количестве были реализованы. Ниже приведено решение с использованием вложенного запроса.
ВЫБРАТЬ
ПартииТоваров.Номенклатура КАК Номенклатура,
ПодЗапрос.ПриходнаяНакладная КАК Приходная,
ПодЗапрос.КоличествоПриход КАК Приход,
ВЫРАЗИТЬ(ПартииТоваров.Регистратор КАК Документ.РеализацияТоваров)
КАК Регистратор,
ПартииТоваров.КоличествоРасход КАК КоличествоРасход
ИЗ
(ВЫБРАТЬ ПЕРВЫЕ 5
ПартииТоваров.Номенклатура КАК Товар,
ПартииТоваров.ДокументПоступления КАК ПриходнаяНакладная,
МАКСИМУМ(ПартииТоваров.КоличествоПриход) КАК КоличествоПриход
ИЗ
РегистрНакопления.ПартииТоваров.Обороты(&НачалоПериода, &КонецПериода, Регистратор,Номенклатура В (&Товары)) КАК ПартииТоваров
СГРУППИРОВАТЬ ПО
ПартииТоваров.Номенклатура,
ПартииТоваров.ДокументПоступления
УПОРЯДОЧИТЬ ПО
КоличествоПриход УБЫВ) КАК ПодЗапрос
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваров.Обороты(, , Регистратор,Номенклатура В (&Товары)) КАК ПартииТоваров
ПО ПодЗапрос.Товар = ПартииТоваров.Номенклатура
И ПодЗапрос.ПриходнаяНакладная = ПартииТоваров.ДокументПоступления
Как было сказано, вложенные запросы могут применяться в условиях оператора «ИЗ» как источник данных. В следующем демонстрационном примере показано, как получить количество товара в выбранной накладной и остаток этого товара на складе.
ВЫБРАТЬ
ТоварыНаСкладах.Номенклатура КАК Товар,
ЕСТЬNULL(ТоварыНаСкладах.ВНаличииОстаток, 0) КАК Остаток,
Товары.Количество КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
&МоментВремени, Номенклатура В
(ВЫБРАТЬ
РеализацияТовары.Номенклатура КАК Товар
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
РеализацияТовары.Ссылка = &Документ
СГРУППИРОВАТЬ ПО
РеализацияТовары.Номенклатура)) КАК ТоварыНаСкладах
ПО Товары.Номенклатура = ТоварыНаСкладах.Номенклатура
ГДЕ
Товары.Ссылка = &Документ
Еще пример вложенного запроса с использованием оператора-условия «В» в свойствах виртуальной таблицы регистра накопления. Вложенный запрос здесь используется как отбор данных, который будет использован в запросе верхнего уровня.
ВЫБРАТЬ
ПодЗапрос.Товар КАК Товар,
ВЫБОР
КОГДА ЕСТЬNULL(ТоварыНаСкладах.ВНаличииОстаток, 0) >= ПодЗапрос.Количество
ТОГДА "Товар достаточно"
ИНАЧЕ "Товара не достаточно"
КОНЕЦ КАК Достаточность
ИЗ
(ВЫБРАТЬ
РасходнаяНакладная.Номенклатура КАК Товар,
СУММА(РасходнаяНакладная.Количество) КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РасходнаяНакладная
ГДЕ
РасходнаяНакладная.Ссылка = &Документ
СГРУППИРОВАТЬ ПО
РасходнаяНакладная.Номенклатура) КАК ПодЗапрос
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ВыбДата, ) КАК ТоварыНаСкладах
ПО ПодЗапрос.Товар = ТоварыНаСкладах.Номенклатура
Фирма 1С не рекомендует использовать вложенные запросы без особой потребности и предлагает заменять их временными таблицами или соединениями таблиц, замечая при этом, что результат такого изменения может быть другим. Такая рекомендация объясняется тем, что при использовании вложенных запросов оптимизатор СУБД не всегда может правильно определить размер выборки вложенного запроса и построить оптимальный план обращений к физическим таблицам базы данных, что сильно (иногда в десятки раз) может замедлить выполнение запроса.
Главное отличие вложенного запроса от временной таблицы – это то, что временную таблицу можно использовать многократно в пакетном запросе, также передавать через менеджер временных таблиц в другие запросы, а вложенный запрос нужно вызывать каждый раз, когда он потребуется и в каждом случае явно указывать текст запроса, что затрудняет читаемость синтаксических конструкций. Также применение временных таблиц дает независимость от вида применяемого СУБД.
Тем не менее, вложенные запросы по-прежнему востребованы и используются в случаях:
- При работе в 1С:Предприятие с версиями платформы 1С 8.3.7 и ниже и при использовании обратной совместимости с такими платформами по-прежнему невозможно использовать временные таблицы в динамических списках;
- Во вложенных динамических списках эффективность применения временных таблиц может быть сильно снижена из-за того, что таблицы требуется создавать при каждом вызове (и поэтому данные не кэшируются). В противном случае данные сохраненной таблицы могут оказаться уже не актуальными;
- Вложенные запросы нужно применять для заведомо небольших выборок, где временные таблицы менее эффективны, так как занимают оперативную память, а при использовании индексирования на больших выборках могут выгружать индексные файлы на носитель, что критически скажется на скорости получения данных из запроса.
Нужно заметить, что еще существуют неявные вложенные запросы. Это:
- Запросы с использованием вложенных соединений. Конструкция вида:
ВЫБРАТЬ Поле1, Поле2, … ИЗ Источник1 ЛЕВОЕ СОЕДИНЕНИЕ Источник_2 ЛЕВОЕ СОЕДИНЕНИЕ Источник_3 ПО (условия для Источник_2 = условие Источник_3) ПО (условия для Источник_2 = условие Источник_1)
Пример в 1С УТ (ред. 11.2.3.300):
ВЫБРАТЬ Товары.Наименование КАК Наименование, ЦеныТовара.Цена КАК Цена, ТоварыОрганизаций.КоличествоПриход КАК Приход ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныТовара ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыОрганизаций.Обороты(, , Регистратор, ) КАК ТоварыОрганизаций ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Товары ПО (ТоварыОрганизаций.Аналитика.Номенклатура = Товары.Ссылка) ПО (ЦеныТовара.Регистратор = ТоварыОрганизаций.Регистратор)
- Запросы с использованием виртуальных таблиц регистров сведений СрезПервых(), СрезПоследних() и регистров накопления Остатки(). Указанные функции могут использовать данные из одной или нескольких физических таблиц базы данных, а их результат транслирован оптимизатором в подзапрос (но не обязательно). Поэтому при использовании соединений с такой виртуальной таблицей нужно обязательно замерять производительность запроса.
Средства СУБД предоставляют механизмы для оптимизации запросов и повышения производительности. Это визуализация построения плана выполнения запроса, проведение трассировки запросов для сбора статистики и выявления узких мест, изучение кода итогового запроса на SQL. Эти механизмы помогут определить, что и как лучше использовать в конкретном случае, – подзапрос, временную таблицу или соединение.
консультация эксперта
самые свежие новости 1 раз в месяц