Эквивалентные запросы:
SELECT *
FROM table1
WHERE id NOT IN (SELECT id FROM table2);
SELECT table1.*
FROM table1
WHERE NOT EXIST (SELECT id FROM table2);
SELECT table1.*
FROM table1
LEFT JOIN table2
ON table1.id = table2.id
WHERE table2.id IS NULL;
Пример. Авторы, которые не участвовали в написании опубликованных книг. (запрос NOT-in-List-Authors)
1) SELECT au_id, au_fname, au_lname
FROM authors
WHERE au_id NOT IN (SELECT au_id FROM title_authors);
2) SELECT au_id, au_fname, au_lname
FROM authors a
WHERE NOT EXISTS
(SELECT *
FROM title_authors ta
WHERE a.au_id = ta.au_id);
3) SELECT a.au_id, a.au_fname, a.au_lname
FROM authors a
LEFT JOIN title_authors ta
ON a.au_id = ta.au_id
WHERE ta.au_id IS NULL;
Подзапросы применяют, если требуется сравнение с результатом агрегатной функции (среднее, максимум…). Если требуется включить в запрос столбцы из нескольких таблиц применяется объединение таблиц (нельзя включить столбцы из таблицы внутреннего запроса).
Простой подзапрос – запрос, который может рассматриваться независимо от внешнего и обрабатывается только один раз.
СУБД выполняет внутренний запрос один раз, затем помещает результат во внешний запрос. Внутренний запрос выполняется до и независимо от внешнего запроса.
Пример. Список авторов, которые живут в городах, где располагаются издательства. (запрос Authors-Publishers#City)
SELECT au_id, city
FROM authors
WHERE city IN
(SELECT city FROM publisher);
Внутренний запрос формирует список городов, где расположены издательства. Внешний использует список в условии отбора строк.
Сложные запросы отличаются более сложным механизмом исполнения. Сложный подзапрос:
- отличается порядком и количеством исполнений;
- не может быть исполнен отдельно, поскольку зависит от внешнего запроса;
- исполняется для каждой строки, выбранной внешним запросом;
всегда обращается к таблице, указанной в предложении FROM внешнего запроса;
- ссылается на столбцы внешнего запроса, которые называются корреляционными переменными.
Структура сложного запроса:
SELECT внешние_столбцы
FROM внешняя_таблица
WHERE значение_внешнего_столбца IN
(SELECT внутренний_столбец
FROM внутренняя_таблица
WHERE внутренний_столбец = внешний_столбец);
Исполнение начинается с внешнего запроса, который выбирает каждую строку внешней таблицы и выполняет внутренний запрос, выбирая строки внутренней таблицы. Для отобранных строк внутренней таблицы проверяется условие внешнего запроса. Процесс продолжается для всех строк внешней таблицы.
Пример. Список книг, уровень продаж которых выше среднего уровня для книг соответствующего типа. (запрос ComplexSUB-List-AVG#Sales)
SELECT
candidate.title_id, candidate.type, candidate.sales
FROM title candidate
WHERE sales >=
(SELECT AVG(sales)
FROM title average
WHERE average.type = candidate.type);
Внутренний подзапрос нельзя выполнить отдельно, поскольку необходимо значение корреляционной переменной candidate.type. Для строки внешней таблицы внутренний запрос рассчитывает средний уровень продаж соответствующего типа (тип книги берется из строки таблицы candidate). Затем внешний запрос сравнивает эту величину со строкой внешней таблицы (значение столбца sales сравнивается со средним). Если продажи выше, значения столбцов строки будут помещены в результат запроса. Далее все повторяется для каждой строки внешней таблицы.
Примечание. Если результат может быть получен как с помощью простого, так и сложного запросов, рекомендуется выбирать простой, поскольку он выполняется быстрее.
Предложение SELECT может содержать вычислимый столбец, который является результатом подзапроса. Подзапрос должен иметь скалярный результат.
Пример. Список книг, цена, средняя цена книг. (запрос SELECT-SUB)
SELECT
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.