Понимание SQL
Шрифт:
SELECT * FROM Salespeople WHERE city=ANY
(SELECT city FROM Customers);
cnum | cname | city | comm |
1001 | Peel | London | 0.12 |
1002 | Serres | San Jose | 0.13 |
1004 | Motika | London | 0.11 |
Таблица 13. 1:
Это означает, что подзапрос должен выбирать значения такого же типа как и те, которые сравниваются в основном предикате. В этом его отличие от EXISTS, который просто определяет, производит ли подзапрос результаты или нет, и фактически не использует эти результаты.
ИСПОЛЬЗОВАНИЕ ОПЕРАТОРОВ IN ИЛИ EXISTS ВМЕСТО ОПЕРАТОРА ANY
Мы можем также использовать оператор IN чтобы создать запрос аналогичный предыдущему :
SELECT *
FROM Salespeople
WHERE city IN
( SELECT city
FROM Customers );
Этот запрос будет производить вывод показанный в Таблице 13.2.
Однако, оператор ANY может использовать другие реляционные операторы кроме равняется (=), и таким образом делать сравнения которые являются выше возможностей IN. Например, мы могли бы найти всех продавцов с их заказчиками которые следуют им в алфавитном порядке (вывод показан в Таблице 13.3)
SELECT *
FROM Salespeople
WHERE sname < ANY
( SELECT cname
FROM Customers);
SELECT * FROM Salespeople
WHERE city IN (SELECT city FROM Customers);
cnum | cname | city | comm |
1001 | Peel | London | 0.12 |
1002 | Serres | San Jose | 0.13 |
1004 | Motika | London | 0.11 |
Таблица 13. 2: Использование IN в качестве альтернативы к ANY
SELECT * FROM Salespeople
WHERE sname < ANY (SELECT cname FROM Customers);
cnum | cname | city | comm |
1001 | Peel | London | 0.12 |
1004 | Motika | London | 0.11 |
1003 | Axelrod | New York | 0.10 |
Таблица 13. 3: Использование оператора ANY с оператором "неравно" (<)
продавцов для их заказчиков которые упорядоченны в алфавитном порядке
( вывод показан в Таблице 13.3)
SELECT *
FROM Salespeople
WHERE sname < ANY
( SELECT cname
FROM Customers);
Все строки были выбраны для Serres и Rifkin, потому что нет других заказчиков чьи имена следовали бы за ими в алфавитном порядке.
Обратите внимание что это является d основнjм эквивалентом следующему запросу с EXISTS, чей вывод показывается в Таблице 13.4:
SELECT *
FROM Salespeople outer
WHERE EXISTS
( SELECT *
FROM Customers inner
WHERE outer.sname < inner.cname );
SELECT * FROM Salespeople outer
WHERE EXISTS (SELECT *
FROM Customers inner WHERE outer.sname < inner.cname);
cnum | cname | city | comm |
1001 | Peel | London | 0.12 |
1004 | Motika | London | 0.11 |
1003 | Axelrod | New York | 0.10 |
Таблица 13.4 Использование EXISTS как альтернатива оператору ANY
Любой запрос который может быть сформулирован с ANY (или, как мы увидим, с ALL ), мог быть также сформулирован с EXISTS, хотя наоборот будет неверно. Строго говоря, вариант с EXISTS не абсолютно идентичен вариантам с ANY или с ALL из-за различия в том как обрабатываются пустые( NULL ) значения (что будет обсуждаться позже в этой главе). Тем ни менее, с технической точки зрения, вы могли бы делать это без ANY и ALL если бы вы стали очень находчивы в использовании EXISTS (и IS NULL ).
Большинство пользователей, однако, находят ANY и ALL более удобными в использовании чем EXISTS, который требует соотнесенных подзапросов.
Кроме того, в зависимости от реализации, ANY и ALL могут, по крайней мере в теории, быть более эффективными чем EXISTS. Подзапросы ANY или ALL могут выполняться один раз и иметь вывод используемый чтобы определять предикат для каждой строки основного запроса. EXISTS, с другой стороны, берет соотнесенный подзапрос, который требует чтобы весь подзапрос повторно выполнялся для каждой строки основного запроса. SQL пытается найти наиболее эффективный способ выполнения любой команды, и может попробовать преобразовать менее эффективную формулу запроса в более эффективную (но вы не можете всегда рассчитывать на получение самой эффективной формулировки ).