Подзапросы, возвращающие несколько столбцов

До сих пор все примеры подзапросов в данной главе возвращали один столбец и одну или более строк. Однако в определенных ситуациях можно использовать подзапросы, возвращающие два или более столб_ цов. Чтобы лучше разобраться в подзапросах, возвращающих несколь_ ко столбцов, полезно сначала взглянуть на пример использования не_ скольких подзапросов, возвращающих один столбец:

mysql> SELECT account_id, product_cd, cust_id
_> FROM account
_> WHERE open_branch_id = (SELECT branch_id
_> FROM branch
_> WHERE name = 'Woburn Branch')
_> AND open_emp_id IN (SELECT emp_id
_> FROM employee
_> WHERE title = 'Teller' OR title = 'Head Teller');
+____________+____________+_________+
| account_id | product_cd | cust_id |
+____________+____________+_________+
| | CHK | |
| | SAV | |
| | CD | |
| | CHK | |
| | SAV | |
| | CD | |
| | BUS | |
+____________+____________+_________+
rows in set (0.00 sec)

Чтобы выявить ID отделения Woburn и ID всех банковских операцио_ нистов, этот запрос использует два подзапроса. Затем содержащий за_ прос использует эту информацию для выбора всех текущих счетов, от_


178 Глава 9. Подзапросы

крытых старшим операционистом в отделении Woburn. Но в таблице employee есть информация об отделении, в котором числится каждый со_ трудник, поэтому те же результаты можно получить путем сравнения столбцов account.open_branch_id и account.open_emp_id с единственным подзапросом к таблицам employee и branch. Для этого в условии фильтра_ ции следует указать в круглых скобках имена обоих столбцов таблицы account в том же порядке, в каком они возвращаются подзапросом:

mysql> SELECT account_id, product_cd, cust_id
_> FROM account
_> WHERE (open_branch_id, open_emp_id) IN
_> (SELECT b.branch_id, e.emp_id
_> FROM branch b INNER JOIN employee e
_> ON b.branch_id = e.assigned_branch_id
_> WHERE b.name = 'Woburn Branch'
_> AND (e.title = 'Teller' OR e.title = 'Head Teller'));
+____________+____________+_________+
| account_id | product_cd | cust_id |
+____________+____________+_________+
| | CHK | |
| | SAV | |
| | CD | |
| | CHK | |
| | SAV | |
| | CD | |
| | BUS | |
+____________+____________+_________+
rows in set (0.00 sec)

Эта версия запроса делает то же самое, что и предыдущий пример, но с помощью всего одного подзапроса, который возвращает два столбца, а не двух подзапросов, возвращающих по одному столбцу.

Конечно, можно было бы переписать предыдущий пример, просто со_ единив три таблицы, без этой возни с подзапросами. Но при изучении SQL полезно увидеть несколько путей достижения одного результата. Вот еще один пример, требующий применения подзапроса. Скажем, от клиентов поступило несколько жалоб, связанных с неверными зна_ чениями в столбцах доступного остатка и отложенного остатка (pending balance) таблицы account. Задача – найти все счета, остатки на которых не соответствуют суммам по операциям для этого счета. Вот частичное решение проблемы:



SELECT 'ALERT! : Account #1 Has Incorrect Balance!' FROM account

WHERE (avail_balance, pending_balance)

(SELECT SUM(), SUM()

FROM transaction WHERE account_id = 1) AND account_id = 1;


Связанные подзапросы

Как видите, здесь нет выражений, суммирующих операции для вычис_ ления доступного и отложенного остатков, но обещаю, что в главе 11, когда мы научимся создавать выражения case, все будет доработано. Но даже в таком виде запрос достаточно полон, чтобы увидеть, что подзапрос генерирует две суммы из таблицы transaction, которые по_ том сравниваются со столбцами avail_balance и pending_balance табли_ цы account. И подзапрос, и основной запрос включают условие фильт_ рации account_id = 1. Таким образом, запрос в его теперешней форме будет проверять только по одному счету за раз. В следующем разделе мы научимся создавать более общую форму запроса, которая будет проверять все счета за одно выполнение.


9306945994407852.html
9306986388394617.html
    PR.RU™