Предикаты, определенные на подзапросах

В состав логических выражений 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 никогда неопределенное значение не принимает.