1
34 24.975
13.24
13.99
13.49
Подзапросы 177
□ SELECT MAX(AVG(price))
FROM products GROUP BY product_type_id;
MAX(AVG(PRICE))
26.22
Значение 26.22 используется во фразе HAVING внешнего запроса для
фильтрации строк группы, у которых средняя цена меньше 26.22. В следующем
запросе вам предлагается версия внешнего запроса, который отбирает
значения product_type_id и средней цены товаров, сгруппированные
по значениям product_type_id:
□ SELECT product_type_id, AVG(price)
FROM products
GROUP BY product_type_id
ORDER BY product_type_id;
PRODUCT_TYPE_ID AVG(PRICE)
1 24.975
2 26.22
3 13.24
4 13.99
13.49
Группы со значениями product_type_id 1, 3, 4 и NULL (пусто) имеют среднюю
цену, которая меньше 26.22. Как и ожидалось, это те же самые группы,
которые были возвращены запросом в самом начале этого раздела.
Подзапросы во фразе FROM (встроенные представления)
Можно поместить подзапрос во фразу FROM внешнего запроса. Такие типы
подзапросов принято называть встроенными представлениями, поскольку
подзапрос предоставляет данные непосредственно внутри фразы
FROM. В приведенном ниже простом примере отбираются товары, у которых
product_type_id меньше трех:
□ SELECT product_id
FROM
(SELECT product_id
FROM products
WHERE product_id < 3);
PRODUCT_ID
1
2
Подзапрос возвращает во внешний запрос строки таблицы products, у
которых product_id меньше трех, а тот, в свою очередь, возвращает и выводит
эти значения product_id. Что касается фразы FROM внешнего запроса,
выходные данные подзапроса можно рассматривать лишь как еще один
источник данных.
178 Глава 6
Следующий пример более полезен. В нем во внешнем запросе из таблицы
products отбираются столбцы productjtype и price, а подзапрос получает
данные о том, сколько раз был продан этот товар:
П SELECT prds.product_id, price, purchases_data.product_count
FROM products prds,
(SELECT product_id, COUNT(product_id) product_count
FROM purchases
GROUP BY product_id) purchases_data
WHERE prds.product_id = purchases_data.product_id;
PRODUCT_ID PRICE PR0DUCT_C0UNT
Подзапрос отбирает из таблицы purchases столбцы product_id и
COUNT(product_id) и возвращает их во внешний запрос. Снова можно видеть,
что выходные данные подзапроса являются лишь другим источником
данных для внешнего-запроса.
Ошибки, с которыми вы можете столкнуться
В этом разделе представлены некоторые ошибки, с которыми вы можете
столкнуться. В частности, вы увидите, что однострочный подзапрос может
возвращать максимум одну строку, а также подзапрос не может содержать
оператор ORDER BY.
Однозначный подзапрос не может возвращать более одной
строки
Если подзапрос возвращает более одной строки, вы получите следующее
сообщение об ошибке:
П 0RA-01427: single-row subquery returns more than one row.
(0RA-01427: однострочный подзапрос возвращает более одной строки)
Например, подзапрос в следующем операторе пытается передать в оператор
равенства (=) во внешнем запросе несколько строк:
П SQL> SELECT рroduct_id, name
2 FROM products
3 WHERE product_id =
4 (SELECT product_id
5 FROM products
6 WHERE name LIKE ‘%e%’ );
(SELECT product_id
ERROR at line 4:
0RA-01427: single-row subquery returns more than one row.
В таблице products есть девять строк, где в названии товара содержится
буква е, и подзапрос пытается передать все эти девять строк во внешний
1 19.95
2 30
3 25.99
441
*
Подзапросы 179
запрос. Поскольку оператор равенства (=) способен обработать только одну
строку, запрос становится недействительным, а пользователю приходит
сообщение об ошибке.
Ниже показано, как правильно возвращать из подзапроса во внешний
запрос несколько строк (см. раздел “Написание многострочных подзапросов”
).
Подзапросы не могут содержать фразу O R D E R BY
Подзапросы не могут содержать фразу ORDER BY. Любое упорядочивание
должно проводиться во внешнем запросе. Так, например, в конце следующего
внешнего запроса содержится фраза ORDER BY, которая сортирует
строки по значениям столбца product_id:
□ SELECT product_id, паше, price
FROM products
WHERE price > (SELECT AVG(price)
FROM products)
ORDER BY product_id DESC;
PRODUCT_ID NAME „ PRICE
5 Z Files 49.99
3 Supernova 25.99
2 Chemistry 30
1 Modern Science 19.95
Написание многострочных подзапросов
Многострочный подзапрос используется для возврата во внешний оператор
SQL одной или нескольких строк. Чтобы обработать подзапрос, возвращающий
несколько строк, во внешнем запросе вы можете использовать
один из операторов IN, ANY или ALL. Как видно из главы 2, эти операторы
можно использовать для проверки того, содержится ли значение
столбца в списке значений, например: