ПРОСТОЙ ПОДЗАПРОС
Выдать фамилии поставщиков, которые поставляют деталь Р2.
SELECT ФАМИЛИЯ
FROM S
WHERE НОМЕР_ПОСТАВЩИКА IN
(SELECT НОМЕР_ПОСТАВЩИКА
FROM SP
WHERE НОМЕР_ДЕТАЛИ = 'P2');
Результат:
ФАМИЛИЯ
Смит
Джонс
Блейк
Кларк
Пояснение. При обработке полного запроса система обрабатывает прежде всего вложенный подзапрос. Этот подзапрос возвращает множество номеров поставщиков, которые поставляют деталь P2, а именно множество ('S1', 'S2', 'S3', 'S4'). Поэтому первоначальный запрос эквивалентен следующему простому запросу:
SELECT ФАМИЛИЯ FROM S
WHERE НОМЕР_ПОСТАВЩИКА IN ('S1'.'S2','S3','S4');
и, следовательно, получаем приведенный ранее результат.
Неявное уточнение фамилии в этом примере требует дополнительного обсуждения. Заметим, в частности, что «НОМЕР-ПОСТАВЩИКА» слева от IN неявным образом уточняется именем таблицы S, в то время как «НОМЕР-ПОСТАВЩИКА» в подзапросе неявно уточняется именем таблицы SP. Справедливо следующее общее правило: предполагается, что неуточненное имя поля должно уточняться именем таблицы (или псевдонимом таблицы — см. примеры 5.2.3–5.2.5 ниже), указанным в той фразе FROM, которая является непосредственной частью того же самого запроса или подзапроса. В случае поля НОМЕР-ПОСТАВЩИКА слева от IN этой фразой является «FROM S», а в случае поля НОМЕР-ПОСТАВЩИКА в подзапросе—это фраза «FROM SP». Для большей ясности повторим первоначальный запрос с явно указанными предполагаемыми уточнениями:
SELECT S. ФАМИЛИЯ
FROM S
WHERE S. НОМЕР_ПОСТАВЩИКА IN
(SELECT SP. НОМЕР_ПОСТАВЩИКА
FROM SP
WHERE SP. НОМЕР_ДЕТАЛИ = 'P2');
Неявные уточнения всегда можно отвергнуть путем задания явных уточнений. Это демонстрируется ниже в примерах 5.2.3–5.2.5.
Прежде чем перейти к нашему следующему примеру подзапроса, необходимо отметить еще один важный момент. Первоначальная задача — «Выдать фамилии поставщиков, которые поставляют деталь P2» — может быть эквивалентным образом выражена как запрос с использованием соединения:
SELECT S. ФАМИЛИЯ
FROM S, SP
WHERE S. НОМЕР_ПОСТАВЩИКА = SP. НОМЕР_ПОСТАВЩИКА
AND SP. НОМЕР_ДЕТАЛИ = 'P2';
Пояснение.
Соединение S и SP по номерам поставщиков представляет собой таблицу из 12 строк (по одной строке для каждой строки SP), каждая из которых состоит из соответствующей строки SP, дополненной значениями ФАМИЛИЯ, СОСТОЯНИЕ и ГОРОД для поставщика, указываемого значением НОМЕР-ПОСТАВЩИКА в этой строке. Из этих 12 строк только четыре относятся к детали P2. Окончательный результат получается, таким образом, выделением значения ФАМИЛИЯ из этих четырех строк.
Обе формулировки первоначального запроса, одна из которых использует подзапрос, а другая — соединение, в равной степени корректны. Вопрос о том, какой из этих формулировок отдать предпочтение,— исключительно дело вкуса данного пользователя.