Коррелированный подзапрос

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

Коррелированный подзапрос выполняется для каждой строки основного запроса. В момент выполнения подзапроса значения столбцов внешнего запроса являются константами.

Пример. Для каждого товара найдем магазины, в которых его можно купить по минимальной цене.

Весь каталог товаров:

SELECT *
  FROM product_price pp
 ORDER BY pp.product_id, pp.price, pp.store_id
# product_id store_id price
1 1 300 10500.00
2 1 800 12000.00
3 1 301 12500.00
4 2 500 26100.00
5 2 600 27500.00
... ... ... ...
13 5 201 23500.00
14 5 500 23500.00
15 5 800 24600.00
... ... ... ...

Оставим записи с минимальной ценой:

SELECT *
  FROM product_price pp
 WHERE pp.price = (SELECT min(ppm.price)
                     FROM product_price ppm
                    WHERE ppm.product_id = pp.product_id)
 ORDER BY pp.product_id, pp.price, pp.store_id
# product_id store_id price
1 1 300 10500.00
2 2 500 26100.00
3 3 500 22000.00
4 4 400 20000.00
5 5 201 23500.00
6 5 500 23500.00
... ... ... ...

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

# product_id store_id price
1 1 300 10500.00
2 1 800 12000.00
3 1 301 12500.00
4 2 500 26100.00
5 2 600 27500.00
... ... ... ...
13 5 201 23500.00
14 5 500 23500.00
15 5 800 24600.00
... ... ... ...

выполняется подзапрос

SELECT min(ppm.price)
  FROM product_price ppm
 WHERE ppm.product_id = pp.product_id

в котором pp.product_id заменяется значеним product_id из обрабатываемой строки.

Для строки

# product_id store_id price
1 1 300 10500.00

запрос

SELECT min(ppm.price)
  FROM product_price ppm
 WHERE ppm.product_id = 1

вернет значение 10500.00, которое совпадает с pp.price. Строка попадает в результат выполнения запроса.

Для строки

# product_id store_id price
2 1 800 12000.00
SELECT min(ppm.price)
  FROM product_price ppm
 WHERE ppm.product_id = 1

вернет значение 10500.00. Во второй строке pp.price = 12000.00. Строка исключается из результата выполнения запроса.

Третья строка исключается аналогично второй.

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

SELECT min(ppm.price)
  FROM product_price ppm
 WHERE ppm.product_id = 2

И так далее..

6.1 Подзапрос одиночной строки

6.3 Подзапрос вернул более одной строки