В качестве иллюстрации приводится фрагмент статьи К. Рупасова «Типичные причины неоптимальной работы запросов и методы оптимизации», фрагмент приведен без изменений.
Не следует использовать подзапросы в условии соединения (и не только в условии соединения, но и вообще в условиях. – Примеч. авт.). Это может привести к значительному замедлению запроса и (в отдельных случаях) к его полной неработоспособности на некоторых СУБД. Пример запроса с использованием подзапроса в условии соединения:
Запрос.Текст = "ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура КАК Номенклатура,
| Цены.Цена КАК ЦенаПрошлогоМесяца
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(...) КАК ОстаткиТоваров
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цена КАК Цены
| ПО Цены.Номенклатура = ОстаткиТоваров.Номенклатура И
| Цены.Период В (
| ВЫБРАТЬ МАКСИМУМ(ЦеныПрошлогоМесяца.Период)
| ИЗ РегистрСведений.Цена КАК ЦеныПрошлогоМесяца
| ГДЕ ЦеныПрошлогоМесяца.Период
| И ЦеныПрошлогоМесяца.Номенклатура = ОстаткиТоваров.Номенклатура
| )
| ГДЕ ОстаткиТоваров.Склад = &Склад";
В данном случае подзапрос в условии соединения используется для получения как бы «среза последних» на конец предыдущего периода. Причем для каждой номенклатуры период может быть разным. Подобный запрос рекомендуется переписать с использованием временных таблиц. Например, это можно сделать следующим образом:
Запрос.Текст = "
// Максимальные даты установки цен в прошлом периоде для данных номенклатур
|ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура КАК Номенклатура,
| МАКСИМУМ(Цены.Период) КАК Период
|ПОМЕСТИТЬ ДатыПоНоменклатурам
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(...) КАК ОстаткиТоваров
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цена КАК Цены
| ПО Цены.Номенклатура = ОстаткиТоваров.Номенклатура И
| Цены.Период
| СГРУППИРОВАТЬ ПО ОстаткиТоваров.Номенклатура
| ГДЕ ОстаткиТоваров.Склад = &Склад;
// Выбрать данные по цене за найденный период
|ВЫБРАТЬ
| ДатыПоНоменклатурам.Номенклатура КАК Номенклатура,
| Цены.Цена КАК ЦенаПрошлогоМесяца
|ИЗ ДатыПоНоменклатурам
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цена КАК Цены
| ПО Цены.Номенклатура = ОстаткиТоваров.Номенклатура И
| Цены.Период = ДатыПоНоменклатурам.Период
";