Глава 11. Связанные подзапросы
Связанные подзапросы в НАVING
В предложении HAVING могут использоваться и связанные подзапросы. В этом случае необходимо ограничить внешние ссылки теми элементами, которые могут не посредственно применяться в самом предложении HAVING. Как стало известно из главы 6, предложение HAVING может использовать только функции агрегирования из предложения SELECT или поля из предложения GROUP ВУ. Это и есть единственные внешние ссылки, которые можно делать, потому что предикат предложения HAVING оценивается для каждой группы из внешнего запроса, а не для каждой строки. Следо вательно, подзапрос будет выполняться один раз для каждой группы выходных дан ных внешнего запроса, а не для каждой отдельной строки.
Предположим, необходимо суммировать значения поля amounts (amt) таблицы
Orders, сгруппировав их по датам и исключив те дни, когда сумма не превышает мак
симальное значение, по крайней мере на 2000.00:
SELECT odate, SUM (amt)
FROM Orders а
GROUP ВУ odate
HAVING SUM (amt) >
(SELECT 2000.00 + МАХ (amt) FROM Orders Ь
WHERE a.odate = b.odate);
Подзаnрос вычисляет максимальное (МАХ) значение для всех строк с одной и той же датой, совпадающей с датой, для которой сформирована очередная группа основ ного запроса. Это должно быть сделано, как показано в данном примере, с помощью предложения WHERE. В самом подзапросе не должно быть предложений GROUP ВУ
и HAVING.
Связанные подзапросы и соединения
Связанные подзапросы имеют близкое сходство с соединениями, так как оба вари анта включают сравнение каждой строки таблицы с каждой строкой другой (или алиа сом той же самой) таблицы. Сходство заключается и в том, что многие операции,
которые можно выполнить с помощью одного варианта, выполнимы и с помощью
другого.
Различие в их применении заключается в ранее упомянутой необходимости ис пользовать иногда DISТINCT в команде соединения Uoin), тогда как этого не требует
ся в подзапросах. Есть также ряд вещей, которые можно сделать только с помощью
одного из этих вариантов. Подзапросы, например, могут использовать агрегатные функции в предикате, позволяя выполнить операции, подобные рассмотренной в пре
дыдущем примере, когда извлекались заказы, величина которых превышала среднее
114
Итоги
значение для данного покупателя. С другой стороны, соединения позволяют получать строки из двух таблиц, участвующих в сравнении, тогда как выходные данные подза просов могут использоваться только в предикатах внешних запросов. Согласно про стому правилу, лучше, вероятно, использовать ту форму запроса, которая кажется интуитивно более понятной, однако предпочтительно знать оба варианта на случай,
если один из них окажется неприемлемым.
Итоги
В главе было рассмотрено одно из сложных понятий SQL - связанные подзапро сы. Мы выяснили, как они соотносятся с операцией соединения, как их можно исполь зовать с функциями агрегирования и с предложением HAVING. Вы ознакомились со
всеми типами подзапросов.
Следующий шаг - введение некоторых специальных операторов, использующих, как и оператор IN, подзапросы в качестве аргументов, но в отличие от IN применяемых толь ко с подзапросами. Первый из них, EXISTS, рассмотрен в главе 12.
115
Работаем на SQL
1.Запишите команду SELECT, использующую связанные подзапросы и выбираю щую имена и номера всех покупателей, рейтинг которых совпадает с максималь
ным значением рейтинга для их города.
2.Запишите два запроса, которые выбирают (по имени и номеру) всех продавцов,
проживающих в городах, где у них нет покупателей. Один запрос должен ис пользовать операцию соединения (join), а второй - связанные подзапросы. Ка кое из решений является более элегантным?
(Подсказка: один из возможных вариантов решения этой задачи - найти всех покупателей, не обслуживаемых данным продавцом, и посмотреть, не находятся ли они в одном городе.)
(Ответы см. в 1tриложении А.)
116
Использование
оператора EXISTS
Глава 12. Использование оператора EXJSTS
В этой главе речь пойдет о специальных операторах, всегда использующих под
запросы в качестве аргументов, в частности, об операторе EXISTS.
Этот оператор применяется для образования предиката, фиксирующего, будет ли
подзапрос генерировать выходные данные. Вы научитесь использовать оператор
EXISTS в обычных и связанных подзапросах. Будут рассмотрены специальные случаи его употребления для агрегатов, NULL-значений и булевых значений. Вы сможете усовершенствовать навыки работы с подзапросами, рассматривая более сложные спо собы их применения.
Как работает оператор EXISTS?
EXISTS - оператор, генерирующий значение "истина" или "ложь", другими сло вами, булево выражение. Это значит, что его можно применять отдельно в предикате или комбинировать с другими булевыми выражениями с помощью операторов AND, OR и NOT. Используя подзапрос в качестве аргумента, этот оператор оценивает его
как истинный, если он генерирует выходные данные, а в противном случае как лож
ный. В отличие от прочих операторов и предикатов, он не может принимать значение unknown. Например, нужно извлечь данные из таблицы Customers в том случае, если один (или более) покупатель из нее находится в San Jose (выходные данные для запро
са представлены на рис. 12. l ):
SELECT cnum, cname, city
FROM Customers
WHERE EXISTS
|
Giovanni |
|
|
|
Liu |
|
|
|
Grass |
|
|
|
Clemens |
London |
|
|
C1sneros |
San Jose |
|
|
Pereira |
Rome |
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 12.1. Использование оператора EXISTS
118