одну или несколько строк.
■ Многостолбцовые подзапросы Возвращают во внешний оператор
SQL более одного столбца.
■ Коррелированные подзапросы Ссылаются на один или несколько
столбцов во внешнем операторе SQL. Подзапрос называют коррелированным,
потому что он связан с внешним оператором SQL посредством
одних и тех же столбцов.
■ Вложенные подзапросы Помещены внутрь другого подзапроса. Подзапросы
можно вкладывать друг в друга до уровня вложения 255.
Написание однострочных подзапросов
Однострочным называется подзапрос, который возвращает во внешний
оператор SQL ноль строк или одну строку. Подзапрос может быть помещен
во фразы WHERE, HAVING или FROM оператора SELECT (см. ниже). Кроме
того, здесь описываются некоторые типы ошибок, с которыми можно
столкнуться при выполнении подзапросов.
Подзапросы во фразе WHERE
Подзапрос можно поместить во фразу WHERE другого запроса. Ниже приведен
простой пример запроса, который содержит подзапрос, помещенный
во фразу WHERE; заметьте, что подзапрос заключается в скобки (...):
П SELECT first_name, last_name
FROM customers
WHERE customer_id =
(SELECT customer_id
Подзапросы 175
FROM customers
WHERE last_name = 'Brown');
FIRST_NAME LAST_NAME
John Brown
В этом примере из строки таблицы customers выбираются имя (first_
name) и фамилия (last_name) для пользователя, чья фамилия - Brown. Давайте
разобьем этот запрос на части и проанализируем, что здесь происходит.
Вот как выглядит подзапрос во фразе WHERE:
□ SELECT customer_id
FROM customers
WHERE last_name = ‘ Brown’ ;
Этот подзапрос выполняется первым (и только один раз) и возвращает
значение customer_id для строки, в которой значение last_name равно
Brown. Значение customer_id для этой строки равно 1, и это значение передается
во фразу WHERE внешнего запроса. Следовательно, внешний запрос
можно считать эквивалентным следующему запросу:
□ SELECT first_name, last_name
FROM customers
WHERE customer_id = 1;
Использование других однострочных операторов
В предыдущем примере во фразе WHERE используется оператор равенства
(=). Можно использовать с однострочными подзапросами и другие операторы
сравнения, например, о , <,>,<= и >=. В следующем примере во фразе
WHERE внешнего запроса используется оператор >; в подзапросе используется
функция AVG() для получения средней цены товара, которая затем
передается во фразу WHERE внешнего запроса. Окончательной целью всего
запроса является получение значений product_id, name и price для товаров,
цена которых выше средней цены товара.
П SELECT product_id, name, price
FROM products
WHERE price >
(SELECT AVG(price)
FROM products);
PRODUCT ID NAME PRICE
1 Modern Science
2 Chemistry
3 Supernova
5 Z Files
25.99
49.99
19.95
30
Разобьем пример на части, чтобы понять, как он работает. Ниже показаны
выходные данные подзапроса, если бы он работал сам по себе (а не в
составе внешнего запроса):
176 Глава 6
П SELECT AVG(price)
FROM products;
AVG(PRICE)
19.7308333
Примечание Этот подзапрос является примером скалярного подзапроса, поскольку он возвращает
ровно одну строку, содержащую один столбец. Значение, возвращаемое скалярным
подзапросом, трактуется как единичное скалярное значение.
Возвращаемое подзапросом значение 19.7308333 используется во фразе
WHERE показанного ранее внешнего запроса, что эквивалентно следующему
запросу:
П SELECT product_id, name, price
FROM products
WHERE price > 19.7308333;
Подзапросы во фразе HAVING
Фраза HAVING используется для фильтрации групп строк (см. главу 4). Можно
поместить подзапрос во фразу HAVING внешнего запроса. Это позволяет
фильтровать группы строк на основании результата, возвращенного подзапросом.
В следующем примере используется подзапрос, помещенный во фразу
HAVING внешнего запроса. Здесь отбираются product_id и средняя цена для
товаров, средняя стоимость которых меньше максимума среднего значения
цены для групп одного и того же типа товаров:
□ SELECT product_type_id, AVG(price)
FROM products
GROUP BY product_type_id
HAVING AVG(price) <
(SELECT MAX(AVG(price))
FROM products
GROUP BY product_type_id)
ORDER BY product_type_id;
PRODUCT_TYPE_ID AVG(PICE)
Подзапрос использует AVG(), чтобы сначала вычислить среднюю цену
для каждого типа товара. Затем результат, возвращаемый AVG ( ) , передается
в функцию МАХ(), которая возвращает максимальное из средних значений.
Снова разобьем пример на части, чтобы понять, как все работает. Ниже
показаны выходные данные подзапроса, когда он работает сам по себе: