Еще раз о подзапросах
Заметим, что в общем случае запрос возвращает множество значений. Поэтому использование подзапроса в предложении WHERE без предикатов EXISTS, IN, ALL и ANY, которые дают булево значение, может привести к ошибке времени выполнения запроса.
Пример 5.8.3
SELECT DISTINCT model, price
FROM PC
WHERE price > (SELECT MIN(price)
FROM Laptop
);
[[ column ]] |
---|
[[ value ]] |
Этот запрос вполне корректен, так как скалярное значение price сравнивается с подзапросом, который возвращает единственное значение. В результате получим четыре модели ПК:
model | price |
---|---|
1121 | 850 |
1233 | 950 |
1233 | 970 |
1233 | 980 |
Однако, если в ответ на вопрос «найти модели и цены ПК, стоимость которых совпадает со стоимостью ноутбуков» написать следующий запрос
SELECT DISTINCT model, price
FROM PC
WHERE price = (SELECT price
FROM Laptop
);
[[ column ]] |
---|
[[ value ]] |
то при выполнении последнего мы можем получить такое сообщение об ошибке:
(«Подзапрос вернул более одного значения. Это не допускается в тех случаях, когда подзапрос следует после =, !=, <, <=, >, >= или когда подзапрос используется в качестве выражения».)
Эта ошибка будет возникать при сравнении скалярного значения с подзапросом, который возвращает более одного значения.
Подзапросы, в свою очередь, также могут содержать вложенные запросы.
С другой стороны, подзапрос, возвращающий множество строк и содержащий несколько столбцов, вполне естественно может использоваться в предложении FROM. Это, например, позволяет ограничить набор столбцов и/или строк при выполнении операции соединения таблиц.
Пример 5.8.4
Этот запрос может быть сформулирован, например, следующим образом:
SELECT prod.maker, lap.*
FROM (SELECT 'laptop' AS type, model, speed
FROM laptop
WHERE speed > 600
) AS lap
INNER JOIN
(SELECT maker, model
FROM product
) AS prod ON lap.model = prod.model;
[[ column ]] |
---|
[[ value ]] |
В результате получим:
maker | type | model | speed |
---|---|---|---|
B | laptop | 1750 | 750 |
A | laptop | 1752 | 750 |
Наконец, подзапросы могут присутствовать в предложении SELECT. Это иногда позволяет весьма компактно сформулировать запрос.
Пример 5.8.5
Здесь вообще можно обойтись одним предложением SELECT в основном запросе:
SELECT (SELECT AVG(price)
FROM Laptop
)
-
(SELECT AVG(price)
FROM PC
) AS dif_price;
[[ column ]] |
---|
[[ value ]] |
В результате получим
dif_price |
---|
328.333 |
Рекомендуемые упражнения: 10, 18, 24, 25, 26, 28, 43, 56, 57, 60, 61, 62, 63, 72, 75, 80, 87, 88, 92, 96, 99, 110, 111, 112, 113, 118, 127, 129