"Пристрелка" к нужным данным
Посмотрите на следующий похожий оператор:
SELECT FirstName, LastName FROM AMERICAN_LEAGUER WHERE CompleteGames > ANY (SELECT CompleteGames FROM NATIONAL_LEAGUER);
В этом случае вместо квантора всеобщности ALL используется квантор существования ANY. Подзапрос (внутренний, вложенный запрос) здесь такой же, как и в предыдущем примере. В результате выполнения этого подзапроса получается полный список игр, в течение которых питчеры Национальной лиги бессменно подавали мяч. А внешний подзапрос возвращает имена и фамилии всех тех питчеров Американской лиги, которые, бессменно подавая мяч, сыграли больше игр, чем какой-либо из питчеров Национальной лиги. Вот в этом-то запросе и используется квантор существования ANY. Вы можете быть уверены, что хотя бы один из питчеров Национальной лиги ни одной игры не провел бессменно на подаче. Поэтому результат, скорее всего, будет включать в себя всех питчеров Американской лиги, которые бессменно провели хотя бы одну игру.
Если заменить ключевое слово ANY эквивалентным ему SOME (какой-то), то результат будет точно такой же. И если истинно утверждение, что "хотя бы один питчер Национальной лиги ни одной игры бессменно не провел на подаче", то тогда можно сказать, что "какой-то питчер Национальной лиги ни одной игры не провел на подаче бессменно".
EXISTS
Для определения того, возвращает ли подзапрос какие-либо строки, вместе с ним можно использовать предикат EXISTS (существует). Если подзапрос возвращает хотя бы одну строку, то этот результат удовлетворяет условию EXISTS и выполняется внешний запрос. Ниже приведен пример использования предиката EXISTS.
SELECT FirstName, LastName FROM CUSTOMER WHERE EXISTS (SELECT DISTINCT CustomerlD FROM SALES WHERE SALES.CustomerID = CUSTOMER.CustomerlD)
В таблице SALES (продажи) хранятся данные обо всех продажах, выполненных компанией. В этой таблице в поле CustomerID находятся идентификаторы покупателей, которые участвовали в какой-нибудь из сделок. В таблице CUSTOMER (покупатель) хранятся имя и фамилия каждого покупателя, но нет никакой информации о конкретных сделках.
Имеющийся в последнем примере подзапрос возвращает строку для каждого покупателя который сделал хотя бы одну покупку. А внешний запрос возвращает имена и фамилии тех кто участвовал в сделках, указанных в таблице SALES.
Предикат EXISTS, как показано в следующем запросе, эквивалентен сравнению COUNT с нулем:
SELECT FirstName, LastName FROM CUSTOMER WHERE 0 <> (SELECT COUNT(*) FROM SALES WHERE SALES.CustomerID = CUSTOMER.CustomerlD);
Для каждой строки таблицы SALES, в которой значение CustomerlD равно какому-либо значению CustomerlD из таблицы CUSTOMER, этот оператор выводит столбцы FirstName (имя) и LastName (фамилия) из таблицы CUSTOMER. Поэтому для каждой сделки, отмеченной в таблице SALES, этот оператор выводит имя и фамилию того покупателя, который в ней участвовал.
UNIQUE
Вместе с подзапросом, как и предикат EXISTS, можно также использовать предикат UNIQUE (уникальный). Если первый из этих предикатов является истинным тогда, когда подзапрос возвращает хотя бы одну строку, то второй из них будет истинным тогда, когда среди возвращенных подзапросом строк нет двух одинаковых. Другими словами, предикат UNIQUE будет истинным, если все возвращаемые подзапросом строки будут уникальными. Проанализируйте следующий пример:
SELECT FirstName, LastName FROM CUSTOMER WHERE UNIQUE (SELECT CustomerID FROM SALES WHERE SALES.CustomerID = CUSTOMER.CustomerID);
Этот оператор возвращает только имена и фамилии всех новых покупателей, которые участвовали лишь в одной из сделок, указанных в таблице SALES. Два значения NULL считаются не равными друг другу и, следовательно, уникальными. И когда ключевое слово UNIQUE применяется к таблице, полученной в результате выполнения подзапроса, а в этой таблице никаких строк, кроме двух неопределенных, больше нет, то и тогда предикат UNIQUE является истинным.