Материал: Graber_Martin_-_SQL_dlya_prostykh_smertnykh_-_2014

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Глава 13. Исtrользование операторов ANY, ALL и SOME

FROM Customers

WHERE city = 'Boston');

полностью воспроизведет таблицу Customers. Поскольку в городе Bostoп нет никаких покупателей, все эти сравнения не имеют большого значения.

ANY и ALL вместо EXISTS с NULL-значениями

NULL-значения также создают некоторые проблемы для рассматриваемых опера­ торов. Когда SQL сравнивает два значения, одно из которых - NULL-значение, ре­ зультат принимает значение unknown (см. главу 5). Unknown-пpeдикaт, также как и fаlsе-предикат, создает ситуацию, когда строка не включается в состав выходных дан­

ных, но результат различен для различных типов запросов, в зависимости от исполь­

зования в них ALL или ANY вместо EXISTS. Рассмотрим приведенные ранее

примеры:

SELECT •

FROM Customers

WHERE rating > ANY

(SELECT rating

FROM Customers

WHERE city = 'Rome');

и:

SELECT •

FROM Customers outer

WHERE EXISTS

(SELECT •

FROM Customers inner

WHERE outer. rating > inner.rating

AND inner.city = 'Rome');

Оба эти запроса ведут себя совершенно одинаково. Предположим, что в таблице Customers есть строка с NULL-значением в столбце rating:

CNUM

CNAME

СIТУ

RAТING

SNUM

2003

Liu

San Jose

NULL

1002

В версии с ANY, когда выбирается поле rating для Mr. Liu в основном запросе, из­ за NULL-значения предикат принимает значение unknown, а строка с Liu не включает­ ся в состав выходных данных. Однако, когда версия NOT EXISTS выбирает эту строку в основном запросе, NULL-значение используется в предикате подзапроса, присваи­ вая ему всякий раз значение unknown. Это значит, что в результате выполнения подза-

140

Функционирование ANY, ALL и EXISTS при потере данных

проса не будет получено ни одного значения и EXISTS примет значение "ложь". Это, в свою очередь, сделает NOT EXISTS истинным. Следовательно, строка с Mr. Liu вклю­

чается в состав выходных данных. Противоречие вытекает из того, что в отличие от

друrих типов предикатов, значение EXISTS - всегда "истина" или "ложь", а никогда

не unknown.

Это и является основанием для использования ANY. NULL-значение не превосхо­ дит любого реального значения. Более того, результат будет тот же, и необходимо ис­

кать меньшее значение.

Использование COUNT вместо EXISTS

Было отмечено, что ANY и ALL могут быть (приближенно) заменены на EXISTS, тогда как обратное неверно. Верно и то, что подзапросы с EXISTS и NOT EXISTS мо­ гут быть заменены теми же самыми подзапросами с COUNT(*) в предложении подза­ проса SELECT. Если в состав выходных данных входит более чем О строк, то это

эквивалентно ситуации EXISTS; в противном случае это то же самое, что NOT EXISTS. Рассмотрим пример (выходные данные для запроса представлены на

рис. 13.12):

SELECT *

FROM Customers outer

WHERE NOT EXISTS

(SELECT *

FROM Customers inner

WHERE outer.rating <= inner.rating

AND inner.city = "Rome");

Его можно представить и так:

SELECT *

FROM Customers outer

WHERE 1 >

(SELECT COUNT(*)

FROM Customers inner

WHERE outer.rating <= inner.rating

AND inner.city = "Rome');

Выходные данные для этого запроса изображены на рис. 13.13.

141

Глава 13. Использование 011ераторов ANY, ALL и SOME

Рис. 13.12. Использование EXISTS со связанным подзапросом

Рис. 13.13. Использование COUNT вместо EXISTS

142

Итоги

Итоги

Эта глава содержит большой объем информации. Подзапросы - тема непростая, поэтому по мере изложения материала обсуждались и возможные варианты, и неодно­ значности. Вы узнали о разных методах работы с ошибками и NULL-значениями. У вас есть теперь несколько способов решения проблемы и возможность выбора опти­

мального варианта.

После разбора наиболее важного и сложного аспекта SQL, оставшийся материал сравнительно прост для понимания. Следующая глава тоже посвящена запросам. Вы научитесь комбинировать выходные данные для любого количества запросов в един­ ственном теле с целью формирования объединения множества запросов с использова­ нием предложения UNION.

143

Работаем на SQL

l.Запишите запрос, выбирающий всех покупателей, рейтинг которых равен или превосходит ANY (в смысле SQL) Serres.

2.Какие выходные данные генерирует эта команда?

3.Запишите запрос, использующий ANY или ALL, который будет находить всех

продавцов, не имеющих покупателей в их городе.

4.Запишите запрос, выбирающий всех покупателей, значение поля amount кото­ рых превышаетлюбое значение (в обычном смысле) для покупателей Лондона.

5.Запишите этот же запрос с использованием МАХ.

(Ответы см. в приложении А.)

144

Источник: https://studfile.net/preview/16418473/