Подзапросы
- Что такое подзапросы
- Фильтрация посредством подзапросов
- Использование подзапросов в качестве вычисляемых полей
Фильтрация посредством подзапросов
Таблицы баз данных, используемые во всех уроках этой книги, являются реляционными таблицами. Заказы хранятся в двух таблицах. Таблица Orders (заказы) содержит по одной строке для каждого заказа; в ней указываются номер заказа, идентификатор клиента и дата заказа. Предметы отдельного заказа хранятся в соответствующей таблице Orderltems. Таблица Orders не содержит информацию о клиентах. Она хранит только идентификатор клиента. Информация о клиентах хранится в таблице Customers (клиенты).
Теперь предположим, что вы хотите получить перечень всех клиентов, которые заказали продукт RGAN01. Что нужно сделать, чтобы получить эту информацию? Для этого нужно сделать следующее.
1. Выбрать номера всех заказов, в которых содержится продукт RGAN01.
2. Выбрать идентификатор клиента для всех клиентов, которые имеют заказы, перечисленные среди номеров заказов, возвращенных на предыдущем шаге.
3. Выбрать информацию о клиенте для всех клиентов, идентификаторы которых были возвращены на предыдущем шаге.
Каждый из этих шагов можно выполнить в виде отдельного запроса. Делая это, вы используете результаты, возвращенные одним оператором SELECT, чтобы заполнить предложение WHERE для следующего оператора SELECT.
Вы можете также использовать подзапросы для того, чтобы объединить все три запроса в одинединственный оператор.
Первый оператор SELECT выбирает столбец order_num для всех продуктов заказа, у которых в столбце prod_id значится RGAN01. Результат представляет собой номера двух заказов, содержащих этот предмет:
FROM OrderItems
WHERE prod_id = 'RGANOl'
order_num
---------------------------
20007
20008
Следующий шаг состоит в выборке идентификаторов клиентов, связанных с заказами 20007 и 20008. Используя предложение IN, о котором говорилось в разеле, "Расширенная фильтрация данных", вы можете создать такой оператор SELECT:
FROM Orders
WHERE order num IN (20007,20008);
cust_id
----------------------
1000000004
1000000005
Теперь объединим эти два запроса путем превращения первого из них (того, который возвращает номера заказов) в подзапрос. Посмотрите на следующий оператор SELECT:
FROM Orders
WHERE order_num IN (SELECT order_num
FROM Orderltems
WHERE prod_id = 'RGANOl);
cust_id
---------------------
10000004
10000005
Подзапросы всегда обрабатываются, начиная с самого внутреннего оператора SELECT в направлении "изнутри наружу". При обработке предыдущего оператора СУБД в действительности выполняет две операции.
Как видите, результат корректен и точно такой же, как полученный путем жесткого кодирования предложения WHERE в предыдущем примере.
Форматируйте ваши Подзапросы
Теперь у нас есть идентификаторы всех клиентов, заказавших продукт RGANOl. Следующий шаг состоит в получении клиентской информации для каждого из этих идентификаторов клиентов. Оператор SQL, осуществляющий выборку двух столбцов, таков:
FROM Customers
WHERE cust_id IN ('1000000004','1000000005');
Вместо жесткого указания идентификаторов клиентов вы можете превратить данное предложение WHERE в подзапрос:
FROM Customers
WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGANOl'));
cust_name cust_contact
-------------- -----------------------
Fun4All Denise L. Stephens
The Tov Store Kim Howard
Чтобы выполнить вышеприведенное выражение SELECT, СУБД должна в действительности выполнить три оператора SELECT. Самый внутренний подзапрос возвращает перечень номеров заказов, который затем используется как предложение WHERE для подзапроса, внешнего по отношению к данному. Этот подзапрос возвращает перечень идентификаторов клиентов, которые используются в предложении WHERE запроса более высокого уровня. Запрос верхнего уровня возвращает искомые данные.
Как видите, за счет использования подзапросов можно создавать очень мощные и гибкие SQL-операторы. Не существует ограничений на число подчиненных запросов, хотя на практике вы можете столкнуться с тем, что снижение производительности подскажет вам, что было использовано слишком много уровней подзапросов.
Только один столбец
Операторы select подзапроса могут выбирать только один столбец. Попытка произвести выборку нескольких столбцов приведет к появлению сообщения об ошибке.
Подзапросы и производительность
Представленные нами коды работают и приводят к получению необходимых результатов. Однако подзапросы — не всегда наиболее эффективный способ выборки данных такого типа. Более подробно об этом рассказано в разделе, "Объединение таблиц", в котором повторно будет рассмотрен этот же самый пример.



