Таблица 12.3: Комбинация EXISTS с обьединением
Внутренний запрос здесь - как и в предыдущем варианте, фактически сообщает, что псевдоним был изменен. Внешний запрос - это обьединение таблицы Продавцов с таблицей Заказчиков, наподобии того что мы видели прежде. Новое предложение основного предиката (AND first.snum=second.snum ) естественно оценивается на том же самом уровне что и предложение EXISTS. Это - функциональный предикат самого обьединения, сравнивающий две таблицы из внешнего запроса в терминах поля snum, которое являются для них общим. Из-за Булева оператора AND, оба условия основного предиката должны быть верны в порядке для верного предиката.
Следовательно, результаты подзапроса имеют смысл только в тех случаях когда вторая часть запроса верна, а обьединение - выполняемо. Таким образом комбинация объединения и подзапроса может стать очень мощным способом обработки данных.
ИСПОЛЬЗОВАНИЕ NOT EXISTS
Предыдущий пример дал понять что EXISTS может работать в комбинации с операторами Буля. Конечно, то что является самым простым способом для использования и вероятно наиболее часто используется с EXISTS - это оператор NOT. Один из способов которым мы могли бы найти всех продавцов только с одним заказчиком будет состоять в том, чтобы инвертировать наш предыдущий пример. (Вывод для этого запроса показывается в Таблице 12.4:)
SELECT DISTINCT snum
FROM Customers outer
WHERE NOT EXISTS
( SELECT *
FROM Customers inner
WHERE inner.snum=outer.snum
AND inner.cnum < > outer.cnum );
EXISTS И АГРЕГАТЫ
Одна вещь которую EXISTS не может сделать - взять функцию агрегата в подзапросе. Это имеет значение. Если функция агрегата находит любые строки для операций с ними, EXISTS верен, не взирая на то, что это - значение функции ; если же агрегатная функция не находит никаких строк, EXISTS неправилен.
SELECT DISTINCT snum FROM Salespeople outer
WHERE NOT EXISTS (SELECT * FROM Customers inner
WHERE inner.snum=outer.snum
AND inner.cnum < > outer.cnum);
cnum |
1003 |
1004 |
1007 |
Таблица 12.4: Использование EXISTS с NOT
Попытка использовать агрегаты с EXISTS таким способом, вероятно покажет что проблема неверно решалась от начала до конца.
Конечно, подзапрос в предикате EXISTS может также использовать один или более из его собственных подзапросов. Они могут иметь любой из различных типов которые мы видели (или который мы будем видеть). Такие подзапросы, и любые другие в них, позволяют использовать агрегаты, если нет другой причины по которой они не могут быть использованы.
Следующий раздел приводит этому пример.
В любом случае, вы можете получить тот же самый результат более легко, выбрав поле которое вы использовали в агрегатной функции, вместо использования самой этой функции. Другими словами, предикат - EXISTS (SELECT COUNT (DISTINCT sname) FROM Salespeople) - будет эквивалентен - EXISTS (SELECT sname FROM Salespeople) который был позволен выше.
Возможные прикладные программы подзапросов могут становиться многократно вкладываемыми. Вы можете вкладывать их два или более в одиночный запрос, и даже один внутрь другого. Так как можно рассмотреть небольшой кусок чтобы получить всю картину работаты этой команды, вы можете воспользоваться способом в SQL, который может принимать различные команды из большинства других языков.
Имеется запрос который извлекает строки всех продавцов которые имеют заказчиков с больше чем одним текущим порядком. Это не обязательно самое простое решение этой проблемы, но оно предназначено скорее показать улучшеную логику SQL. Вывод этой информации связывает все три наши типовых таблицы:
SELECT *
FROM Salespeople first
WHERE EXISTS
( SELECT *
FROM Customers second
WHERE first.snum=second.snum
AND 1 <
( SELECT COUNT (*)
FROM Orders
WHERE Orders.cnum=
second.cnum ));
Вывод для этого запроса показывается в Таблице 12.5.
FROM Salespeople first WHERE EXISTS
(SELECT * FROM Customers second
WHERE first.snum=second.snum
AND 1 < (SELECT CONT (*) FROM Orders
WHERE Orders.cnum=second.cnum));
cnum | cname | city | comm |
1001 | Peel | London | 0.17 |
1002 | Serres | San Jose | 0.13 |
1007 | Rifkin | Barselona | 0.15 |
Таблица 12.5: Использование EXISTS с комплексным подзапросом
Мы могли бы разобрать вышеупомянутый запрос примерно так: