Лекция 11н Вложенные запросы SQLx

advertisement
Лекция 11
Вложенные запросы
Вопрос 1. Простые вложенные подзапросы
Вложенный подзапрос - это подзапрос, заключенный в круглые скобки и
вложенный в WHERE (HAVING) фразу предложения SELECT или других
предложений, использующих WHERE фразу. Вложенный подзапрос может
содержать в своей WHERE (HAVING) фразе другой вложенный подзапрос и
т.д. Нетрудно догадаться, что вложенный подзапрос создан для того, чтобы
при отборе строк таблицы, сформированной основным запросом, можно было
использовать данные из других таблиц.
Существуют простые и коррелированные вложенные подзапросы. Они
включаются в WHERE (HAVING) фразу с помощью условий IN, EXISTS или
одного из условий сравнения ( = | <> | < | <= | > | >= ). Простые вложенные
подзапросы
обрабатываются
системой
"снизу
вверх".
Первым
обрабатывается вложенный подзапрос самого нижнего уровня. Множество
значений, полученное в результате его выполнения, используется при
реализации подзапроса более высокого уровня и т.д.
Запросы с коррелированными вложенными подзапросами обрабатываются
системой в обратном порядке. Сначала выбирается первая строка рабочей
таблицы, сформированной основным запросом, и из нее выбираются значения
тех столбцов, которые используются во вложенном подзапросе (вложенных
подзапросах). Если эти значения удовлетворяют условиям вложенного
подзапроса, то выбранная строка включается в результат. Затем выбирается
вторая строка и т.д., пока в результат не будут включены все строки,
удовлетворяющие вложенному подзапросу (последовательности вложенных
подзапросов).
Следует отметить, что SQL обладает большой избыточностью в том смысле,
что он часто предоставляет несколько различных способов формулировки
одного и того же запроса. Поэтому во многих примерах данной главы будут
использованы уже знакомые нам по предыдущей главе концептуальные
формулировки запросов. И несмотря на то, что часть из них успешнее
реализуется с помощью соединений, здесь все же будут приведены их
варианты с использованием
вложенных подзапросов. Это связано с необходимостью детального
знакомства с созданием и принципом выполнения вложенных подзапросов, так
как существует немало задан (особенно на удаление и измены—; данных),
которые не могут быть реализованы другим способом. Кроме того, разные
формулировки одного и того же запроса требуют для своего выполнения
различных ресурсов памяти и могут значительно отличаться по времени
реализации в разных СУБД.
Использование вложенных подзапросов связано с некоторыми ограничениями.
При создании вложенных подзапросов обычно принято придерживаться
следующих правил:
 Вложенный подзапрос должен быть заключен в скобки;
 Если в данном месте задано выражение использующее одно значение, то
вложенный подзапрос возвращать одно значение;
 Вложенный подзапрос нельзя использовать в директиве ORDER BY;
 В директиве IN вложенный запрос не может иметь в списке
столбцов более одного столбца;
В директиве EXISTS вложенный запрос задается в виде SELECT
*;
 Вложенный запрос не может содержать директивы ORDER BY, COMPUTE
BY или SELECT INTO.
Вложенные простые подзапросы демонстрируют следующие примеры.
Вывести сведения о книгах, которые были проданы хотя бы один раз:
SELECT id, publishers, author, title, price, style КОД
FROM Books
WHERE id IN (SELECT book FROM Sales)
Вывести сведения о книгах, которые были проданы 16 января 2005года:
SELECT id, publishers, author, title
FROM Books WHERE id = (SELECT book
FROM Sales WHERE data_sale='2005/01/16')
Найти все книги по зарубежным детективам в названии, которых встречается
слово "Тайна":
КОД
SELECT id, publishers, author, title, style
FROM Books WHERE style='Заруб. детективы1 AND
id IN (SELECT id FROM Books WHERE title LIKE '%Тайна%')
Пример, демонстрирующий использование агрегатных функций в подзапросе:
SELECT * FROM Customers WHERE age>=(SELECT AVG(age)
FROM Customers)
Вопрос 2. Коррелированные вложенные подзапросы
Коррелированный вложенный запрос ссылается на таблицу внешнего запроса
и обрабатывает каждую его строку. В этом отношении коррелированный
вложенный запрос отличается от обычного вложенного запроса тем, что
последний выполняется независимо от внешнего запроса. В
следующем примере запрос с объединением переписан как
коррелированный вложенный запрос. Оба запроса выводят одну и ту же
информацию: список всех заказчиков, которые живут в одном городе и имеют
одинаковые имена:
Используется объединение:
SELECT Custl.fname, Custl.Iname, Cust2.fname, Cust2.1name,
Custl.address
FROM Customers AS Custl INSZr. JOIN
Customers AS Cust2 CN Custl- address = Cust2.address AND
Custl. Iname = Cust2 . Inar<e WHERE
Custl.id < Cust2._d ORDER BY
Custl.address
Используется коррелированный вложенный запрос
SELECT Custl.fname, Custl.Iname, Custl.address FROM Customers AS Custl WHERE
Custl.Iname IN (SELECT Iname FROM Customers AS Cust2
WHERE Custl.address = Cust2.address AND Custl.Iname =
Cust2 . Iname AND Custl. idoCust2 . id)
Order By Custl.address
Вопрос 3. Запросы, использующие EXISTS
Квантор EXISTS (существует) - понятие, заимствованное из формальной
логики. В языке SQL предикат с квантором существования представляется
выражением EXISTS (SELECT * FROM ...). Такое выражение считается
истинным только тогда, когда результат вычисления "SELECT * FROM ..."
является непустым множеством, т.е. когда существует какая-либо запись в
таблице, указанной во фразе FROM подзапроса, которая удовлетворяет
условию WHERE подзапроса (Практически этот подзапрос всегда будет
коррелированным множеством.)
Например, нам надо составить запрос, который выводил бы сведения о тех
заказчиках, которые покупали книги с идентификатором 2
SELECT * FROM Customers WHERE NOT EXISTS (SELECT customer FROM
Sales WHERE book = 2 AND Customers.id=Sales.customer)
Хотя этот пример только показывает иной способ формулировки запроса для
задачи, решаемой и другими путями (с помощью оператора IN или
соединения), EXISTS представляет собой одну из наиболее важных
возможностей SQL, Фактически любой запрос, который выражается через IN,
может быть альтернативным образом сформулирован также с помощью
EXISTS. Однако обратное высказывание несправедливо.
Download