Предикаты, определенные на подзапросах
В состав логических выражений SQL могут входить предикаты, определенные на подзапросах: признак того, что подзапрос не пуст (Exists), признак того, что все элементы удовлетворяют некоторому условию (All) и признак того, что существует хотя бы один элемент, удовлетворяющий некоторому условию (Any, Some).
Функция Exists истинна, если ее аргумент (подзапрос) содержит хотя бы один элемент, в противном случае она ложна. Легко видеть, что в подзапросе этой функции использование агрегатных функций бессмысленно. Рассмотрим применение функции Exists на примерах.
Пример
1. Выбрать всех покупателей из Тулы, если хотя бы один из них сделал заказ:
Select * From Покупатель
Where город=’Тула’ and Exists
(Select * From Заказ Where ном_пок in
(Select ном_пок From Покупатель Where город=’Тула’));
Заметим, что здесь в подзапросе используется конструкция Select *… Использование ее в Exists – это единственный случай корректного употребления варианта «*» в подзапросе.
2. Выбрать номера всех продавцов, у которых более одного покупателя:
Select Distinct ном_прод From Заказ a
Where Exists(Select * From Заказ b Where a.ном_прод=b.ном_прод
and a.ном_пок<>b.ном_пок);
В данном случае Exists используется в сочетании со связанным подзапросом. Дополним предыдущий пример соединением: выберем имена всех продавцов, у которых более одного покупателя:
Select Distinct a.ном_прод, имя_прод From Заказ a, Продавец c
Where Exists(Select * From Заказ b
Where a.ном_прод=b.ном_прод and a.ном_пок<>b.ном_пок)
and a.ном_прод=c.ном_прод;
Конец примера
Предикат All имеет вид All <переменная> θ (<подзапрос>), где θ – операция сравнения. Он принимает истинное значение, если каждое значение подзапроса удовлетворяет условию, определяемому операцией θ. Естественно, этот предикат редко может применяться для операции равенства: в этом случае все элементы выборки должны быть равны между собой. Неравенство – более содержательная операция, она обозначает, что левая часть не равна ни одному из элементов выборки. Правда, этот предикат легко реализуется операцией in. Более интересны операции «больше», «меньше» и т.п. Рассмотрим применение предиката All на примере.
Пример
Выбрать всех покупателей, значимость которых выше значимости любого покупателя из Тулы:
Select * From Покупатель
Where значимость>All(Select значимость From Покупатель
Where город =’Тула’);
Этот же запрос можно сформулировать с Exists:
Select * From Покупатель a
Where not Exists(Select * From Покупатель b
Where a.значимость<=b.значимость and b.город=’Тула’);
Конец примера
Предикат Any (синоним – Some) имеет вид Any <переменная> θ (<подзапрос>), где θ – операция сравнения. Он принимает истинное значение, если хотя бы одно значение подзапроса удовлетворяет условию, определяемому операцией θ. Этот предикат чаще используется для операции равенства, чем для «больше», «меньше» и т.п. Рассмотрим применение предиката Any на примере.
Пример
Выбрать всех покупателей, живущих в городе, где есть продавец:
Select * From Покупатель Where город= Any(Select город From Продавец);
Этот же запрос можно сформулировать с in:
Select * From Покупатель Where город in (Select город From Продавец);
С Exists этот запрос выглядит так:
Select * From Покупатель a Where
Exists(Select * From Продавец b Where a.город=b.город);
Конец примера
Любой запрос как с Any, так и с All, может быть выражен через Exists, но в этом случае часто требуется более глубокая вложенность запросов и нередко встречаются связанные подзапросы.
Уточним, как ведут себя предикаты Any, All и Exists в особых случаях. Для пустой выборки All принимает значение истина, Any и Exists – ложь. При сравнении с null предикаты Any и All принимают неопределенное значение, Exists никогда неопределенное значение не принимает.