Лабораторная работа № 8
Использование подзапросов
Цель: Научиться создавать подзапросы с помощью языка SQL в среде СУБД InterBase.
Теоретическая часть
Существуют простые и коррелированные вложенные подзапросы. Они включаются в WHERE (HAVING) фразу с помощью условий IN, EXISTS или одного из условий сравнения (= | <> | < | <= | > | >=).
Простые вложенные подзапросы
Простые вложенные подзапросы используются для представления множества значений, исследование которых должно осуществляться в каком-либо предикате IN, как иллюстрируется в следующем примере: выдать название и статус поставщиков продукта с номером 11, т.е. помидор.
SELECT Название, Статус ¦ Результат: Название Статус
FROM Поставщики ¦ -------- ----------
WHERE ПС IN ¦ СЫТНЫЙ рынок
(SELECT ПС ¦ УРОЖАЙ коопторг
FROM Поставки ¦ ЛЕТО агрофирма
WHERE ПР = 11); ¦ КОРЮШКА кооператив
Этот подзапрос выдает множество номеров поставщиков, которые поставляют продукт с кодом ПР = 11, а именно множество (1, 5, 6, 8). Поэтому первоначальный запрос эквивалентен такому простому запросу:
SELECT Название, Статус
FROM Поставщики
WHERE ПС IN (1, 5, 6, 8);
Подзапрос с несколькими уровнями вложенности можно проиллюстрировать на том же примере. Пусть требуется узнать не поставщиков продукта 11, как это делалось в предыдущих запросах, а поставщиков помидор, являющихся продуктом с номером 11. Для этого можно дать запрос
SELECT Название, Статус
FROM Поставщики
WHERE ПС IN
(SELECT ПС
FROM Поставки
WHERE ПР IN
(SELECT ПР
FROM Продукты
WHERE Продукт = 'Помидоры');
В данном случае результатом самого внутреннего подзапроса является только одно значение (11). Как уже было показано выше, подзапрос следующего уровня в свою очередь дает в результате множество (1, 5, 6, 8). Последний, самый внешний SELECT, вычисляет приведенный выше окончательный результат. Вообще допускается любая глубина вложенности подзапросов.
Тот же результат можно получить с помощью соединения
SELECT Название, Статус
FROM Поставщики, Поставки, Продукты
WHERE Поставщики.ПС = Поставки.ПС
AND Поставки.ПР = Продукты.ПР
AND Продукт = 'Помидоры';
При выполнении этого компактного запроса система должна одновременно обрабатывать данные из трех таблиц, тогда как в предыдущем примере эти таблицы обрабатываются поочередно. Естественно что для их реализации тебуются различные ресурсы памяти и времени, однако этого невозможно ощутить при работе с ограниченным объемом данных в иллюстративной базе ПАНСИОН.
Использования одной и той же таблицы во внешнем и вложенном подзапросе.
Выдать номера поставщиков, которые поставляют хотя бы один продукт, поставляемый поставщиком 6.
SELECT DISTINCT ПС ¦ Результат: ПС
FROM Поставки ¦ --
WHERE ПР IN ¦ 1
(SELECT ПР ¦ 3
FROM Поставки ¦ 5
WHERE ПС = 6); ¦ 6
¦ 8
Отметим, что ссылка на Поставки во вложенном подзапросе означает не то же самое, что ссылка на Поставки во внешнем запросе. В действительности, два имени Поставки обозначают различные значения. Чтобы этот факт стал явным, полезно использовать псевдонимы, например, X и Y:
SELECT DISTINCT X.ПС
FROM Поставки X
WHERE X.ПР IN
(SELECT Y.ПР
FROM Поставки Y
WHERE Y.ПС = 6);
Здесь X и Y произвольные псевдонимы таблицы Поставки, определяемые во фразе FROM и используемые как явные уточнители во фразах SELECT и WHERE. Напомним, что псевдонимы определены лишь в пределах одного запроса.