
- •Новосибирская государственная академия экономики и управления
- •«Базы данных»
- •Новосибирск 2000
- •Введение
- •1. Простые запросы
- •2. Многотабличные запросы
- •3. Подзапросы
- •4. Операторы exists и not exists
- •5. Встроенные функции
- •6. Фразы group by и having
- •7. Встроенные функции и подзапросы
- •9. Операции изменения данных
3. Подзапросы
Подзапрос. Запрос внутри запроса
Подзапрос может помещаться в команду WHERE запроса, в результате чего возможности команды WHERE расширяются. Рассмотрим пример.
Запрос: Каковы специальности рабочих, назначенных на здание 435?
SELECT SKTLL_TYPE
FROM WORKER WHERE WORKER_ID IN
(SELECT WORKER_ID
FROM ASSIGNMENT
WHERE BLDG_ID = 435)
Подзапрос в этом примере
(SELECT WORKER_ID
FROM ASSIGNMENT
WHERE BLDG_ID = 435)
Запрос, в котором содержится подзапрос, называется внешним запросом или главным запросом. Подзапрос приводит к созданию следующего множества ИД (идентификаторов) работников:
WORKER ID
2920
1412
1311
Внешний запрос. Главный запрос, в котором содержатся все подзапросы.
Затем это множество ИД занимает место подзапроса во внешнем запросе. С этого момента выполняется внешний запрос, использующий множество, созданное подзапросом. Внешний запрос обрабатывает каждую строку таблицы WORKER в соответствии с условием WHERE. Если WORKER_ID строки лежит в (IN) множестве, созданном подзапросом, то SKILL_TYPE строки выбирается и выводится в результирующей таблице:
SKILL TYPE
Штукатур
Кровельщик
Электрик
Очень важно, что фраза SELECT подзапроса содержит WORKER_ID и только WORKER_ID. В противном случае фраза WHERE внешнего запроса, означающая, что WORKER_ID лежит в множестве ИД работников, не имела бы смысла.
Обратите внимание, что подзапрос может логично выполняться прежде, чем хотя бы одна строка рассматривается главным запросом. В некотором смысле подзапрос независим от главного запроса. Он может выполняться как полноценный запрос. Мы говорим, что такой подзапрос не коррелирован с главным запросом. Как мы вскоре увидим, подзапросы могут быть коррелированными.
Некоррелированный подзапрос. Подзапрос, значение которого не зависит ни от какого внешнего запроса.
Приведем пример подзапроса внутри подзапроса.
Запрос: Перечислить работников, назначенных на здания офисов.
Снова мы рассматриваем запрос, с помощью которого мы изучали соединение.
SELECT WORKER_MAME
FROM WORKER
WHERE WORKER_ID IN
(SELECT WORKER_ID
FROM ASSIGNMENT
WHERE BLDG_ID IN
(SELECT BLDG_ID
FROM BUILDING
WHERE TYPE = 'Офис'))
Результат:
NAME
М.Фарадей
К.Немо
Р.Гаррет
П.Мэйсон
Г.Риковер
Дж.Барристер
Обратите внимание, что нам нигде не нужно указывать перед именами столбцов имена таблиц, поскольку каждый подзапрос обрабатывает одну и только одну таблицу, так что никаких неопределенностей возникнуть не может.
Выполнение запроса происходит в порядке изнутри наружу. То есть самый внутренний запрос (или «самый нижний») выполняется первым, затем выполняется содержащий его подзапрос, а затем внешний запрос.
Коррелированные подзапросы. Все рассмотренные выше подзапросы были независимы от главных запросов, в которых они использовались. Под независимостью мы подразумеваем, что подзапросы могут выполняться сами по себе в качестве полноценных запросов. Теперь мы перейдем к рассмотрению класса подзапросов, результаты выполнения которых могут зависеть от строки, рассматриваемой главным запросом. Такие подзапросы называются коррелированными подзапросами.
Коррелированный подзапрос. Подзапрос, результат которого зависит от строки, рассматриваемой главным запросом.
Запрос: Перечислить работников, чьи почасовые ставки выше, чем ставки их менеджеров.
SELECT WORKER_NAME
FROM WORKER A
WHERE A.HRLY_RATE >
(SELECT B.HRLY_RATE
FROM WORKER В
WHERE B.WORKER_ID = A.SUPV_ID)
Результат:
NAME
К. Немо
Логические этапы выполнения этого запроса таковы:
1. Система создает две копии таблицы WORKER: копию А и копию В. В соответствии с тем, как мы их определили, А относится к работнику, В - к менеджеру.
2. Затем система рассматривает каждую строку А. Данная строка выбирается, если она удовлетворяет условию WHERE. Это условие означает, что строка будет выбрана, если величина HRLY_RATE в ней больше, чем HRLY_RATE, порожденная подзапросом.
3. Подзапрос выбирает величину HRLY_RATE из строки В, WORKER_ID которой равен SUPV_ID строки А, в данный момент рассматриваемой главным запросом. Это HRLY_RATE менеджера.
Обратите внимание, что поскольку A.HRLY_RATE может сравниваться только с одной величиной, подзапрос должен выдавать только одну величину. Эта величина меняется в зависимости от того, какая строка А рассматривается. Таким образом, подзапрос коррелирует с главным запросом. Мы встретимся с другими примерами коррелированных подзапросов позже, когда будем изучать встроенные функции.
Задание 3. Выполните следующие запросы к базе данных «Перевозки».
Перечислить города, получавшие грузы от клиентов с годовым доходом свыше 15 миллионов долларов.
Перечислить имена водителей, доставлявших грузы весом более 100 фунтов.
Перечислить названия и годовые доходы клиентов, отправлявших грузы весом более 100 фунтов.
Перечислить названия и годовые доходы клиентов, чьи грузы доставлял водитель Дженсен.