В одной из прошлых статей мы разбирали, что такое соединение таблиц через JOIN.
Продолжим изучение SQL и в этой статье вы узнаете, что такое подзапросы и как применять их.
SQL-запросы – это инструкции SELECT
. Как правило, большинство простых примеров представляют собой простые запросы на выборку: посредством отдельных инструкций извлекаются данные из нужных таблиц.
В SQL можно также создавать подзапросы, то есть запросы, которые вложены в другие запросы. Почему возникает потребность в подзапросах? Предлагаю рассмотреть несколько примеров, чтобы ответить на этот вопрос. Но для начала рассмотрим БД.
Знакомство с базой данных
В примере статьи будет использована реляционная база данных.
- Orders – содержит по одной строке для каждого заказа, в ней указываются номер заказа.
- OrderItems – хранятся отдельные элементы заказов в таблице.
- Customers – данные по клиентам.
Схема выглядит следующим образом:
Фильтрация
Предположим, что вам нужно получить список всех клиентов, которые заказывали товар ‘RGAN01’. Для этого потребуется сделать следующее:
- Извлечь номера всех заказов, содержащих данный товар.
- Получить id клиентов, которые сделали заказы с этим товаром.
- Извлечь информацию о клиентах.
Каждый из этих пунктов можно сделать в виде отдельного запроса. Поступая так, вы используете результаты, возвращаемые одной функцией SELECT
, чтобы заполнить предложение WHERE
для следующей функции SELECT
.
Однако можно использовать подзапросы для того, чтобы объединить все три запроса в одну инструкцию.
Первый запрос извлекает столбец order_num
для всех элементов заказов, где prod_id = 'RGAN01'
. В результате мы получим номера двух заказов.
SELECT order_num FROM OrderItems
WHERE prod_id = 'RGAN01'
Следующий шаг заключается в получении id клиентов, связанных с заказами 20007 и 20008. Воспользуемся IN
для получения таких клиентов.
SELECT cust_id FROM Orders
WHERE order_num IN (20007, 20008)
Теперь объединим два запроса путем превращения первого в подзапрос.
SELECT cust_id FROM Orders
WHERE order_num IN (
SELECT order_num FROM OrderItems
WHERE prod_id = 'RGAN01'
)
Анализ
Подзапросы всегда обрабатываются начиная с самой внутренней инструкции SELECT
в направлении “изнутри наружу”. Вначале выполняется подзапрос:
SELECT order_num FROM OrderItems
WHERE prod_id = 'RGAN01'
В результате возвращаются два номера заказа: 20007 и 20008. Эти два значения передаются в WHERE
внешнего запроса в формате с разделителем в виде запятой. Далее выполняется вторая (а по сути первая) часть запроса:
SELECT cust_id FROM Orders
WHERE order_num IN (20007, 20008)
Теперь у нас есть id всех клиентов, заказавших товар ‘RGAN01’. Следующий шаг состоит в том, чтобы получить клиентскую информацию для каждого id.
SELECT cust_name, cust_contact FROM Customers
WHERE cust_id IN (
SELECT cust_id FROM Orders
WHERE order_num IN (
SELECT order_num FROM OrderItems
WHERE prod_id = 'RGAN01'
)
)
Чтобы выполнить такой запрос, СУБД должна обработать 3 инструкции SELECT
. Самый внутренний подзапрос возвращает перечень номеров заказов, который используется в предложении WHERE
, по которому мы получаем перечень cust_id
. И на последнем этапе мы получаем названием и контактное лицо клиента.
Инструкции
SELECT
в подзапросах могут возвращать только один столбец. При попытке извлечь несколько столбцов возникнет ошибка.
Подзапросы не всегда самый эффективный способ получения данных.
В следующей главе мы рассмотрим иной способ, а также расскажем про использование подзапросов в качестве вычисляемых полей.