Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab8_запросы.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
176.64 Кб
Скачать

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. Выполните следующие запросы к базе данных «Перевозки».

  1. Перечислить города, получавшие грузы от клиентов с годовым дохо­дом свыше 15 миллионов долларов.

  2. Перечислить имена водителей, доставлявших грузы весом более 100 фунтов.

  3. Перечислить названия и годовые доходы клиентов, отправлявших грузы весом более 100 фунтов.

  4. Перечислить названия и годовые доходы клиентов, чьи грузы достав­лял водитель Дженсен.