FROM Orders a, Customers b
WHERE a.cnum=b.cnum
AND b.city ='San_Jose' );
Даже если наименьший порядок в таблице был для заказчика из San Jose, то был второй наибольший; следовательно почти все строки будут выбраны. Простой способ запомнить, что < ANYзначение меньшее чем наибольшее выбранное значение, а > ANYзначение большее чем наименьшее выбранное значение.
Рисунок 11 Использование ANY с объединением
Фактически, вышеуказанные команды весьма похожи на следующее - (вывод показан на Рисунке 13):
SELECT *
FROM Orders
WHERE amt<(SELECT MAX (amt)
FROM Orders a, Customers b
WHERE a.cnum=b.cnum
AND b.city='San_Jose' );
Рисунок 12 Использование агрегатной функции вместо ANY
Специальный оператор all
С помощью ALL, предикат является верным, если каждое значение выбранное подзапросом удовлетворяет условию в предикате внешнего запроса. Если мы хотим пересмотреть наш предыдущий пример чтобы вывести только тех заказчиков чьи оценки, фактически, выше чем у каждого заказчика в Rome, мы можем ввести следующее чтобы произвести вывод показанный в Рисунке 13:
SELECT *
FROM Customers
WHERE rating>ALL
(SELECT rating
FROM Customers
WHERE city='Rome');
Рисунок 13 Использование оператора ALL
Этот оператор проверяет значения оценки всех заказчиков в Риме. Затем он находит заказчиков с оценкой большей чем у любого из заказчиков в Риме. Самая высокая оценка в Риме - у Giovanni (200). Следовательно, выбираются только значения выше этих 200.
Как и в случае с ANY, мы можем использовать EXISTS для производства альтернативной формулировки такого же запроса - (вывод показан на Рисунке 14):
SELECT *
FROM Customers outers
WHERE NOT EXISTS
( SELECT *
FROM Customers inners
WHERE outers.rating<=inners.rating
AND inners.city = 'Rome' );
Рисунок 14 Использование EXISTS в качестве альтернативы к ALL
Равенства и неравенства
ALL используется в основном с неравенствами чем с равенствами, так как значение может быть "равным для всех" результатом подзапроса только если все результаты, фактически, идентичны. Посмотрите следующий запрос:
SELECT *
FROM Customers
WHERE rating = ALL
(SELECT rating
FROM Customers
WHERE city='San_Jose' );
Эта команда допустима, но, c этими данными, мы не получим никакого вывода. Только в единственном случае вывод будет выдан этим запросом - если все значения оценки в San Jose окажутся идентичными. В этом случае, можно сказать следующее :
SELECT *
FROM Customers
WHERE rating =
( SELECT DISTINCT rating
FROM Customers
WHERE city='San Jose' );
Основное различие в том, что эта последняя команда должна потерпеть неудачу если подзапрос выведет много значений, в то время как вариант с ALL просто не даст никакого вывода. В общем, не самая удачная идея использовать запросы которые работают только в определенных ситуациях подобно этой. Так как ваша база данных будет постоянно меняться, это неудачный способ, чтобы узнать о ее содержании. Однако, ALL может более эффективно использоваться с неравенствами, то есть с оператором "< >". Но учтите что сказанное в SQL что - значение которое не равняется всем результатам подзапроса, - будет отличаться от того же но сказанного с учетом грамматики Английского языка. Очевидно, если подзапрос возвращает много различных значений, как это обычно бывает, ни одно отдельное значение не может быть равно им всем в обычном смысле. В SQL, выражение - < > ALL - в действительности соответствует " не равен любому " результату подзапроса. Другими словами, предикат верен, если данное значение не найдено среди результатов подзапроса. Следовательно, наш предыдущий пример противоположен по смыслу этому примеру (с выводом показанным в Рисунке 16):
SELECT *
FROM Customers
WHERE rating<>ALL
( SELECT rating
FROM Customers
WHERE city='San Jose' );
cnum | cname | city | rating | snum |
Hoffman | London | |||
Clemens | London | |||
Pereira | Rome |
Рисунок 16 Использование ALL с < >
Вышеупомянутый подзапрос выбирает все оценки для города San Jose. Он выводит набор из двух значений: 200 (для Liu) и 300 (для Cisneros). Затем, основной запрос, выбирает все строки, с оценкой не совпадающей ни с одной из них - другими словами все строки с оценкой 100. Вы можете сформулировать тот же самый запрос используя оператор NOT IN:
SELECT*
FROM Customers
WHERE rating NOT IN
( SELECT rating
FROM Customers
WHERE city='San Jose' );
Вы могли бы также использовать оператор ANY:
SELECT *
FROM Customers
WHERE NOT rating = ANY
( SELECT rating
FROM Customers
WHERE city ='San Jose' );
Вывод будет одинаков для всех трех условий.