
- •Содержание
- •12.1. Использование подзапросов.
- •12.2. Дополнительные возможности использования подзапросов, возвращающих единичное значение.
- •12.2.1. Использование предложения exists.
- •12.2.2. Использование предложения singular.
- •12.3. Использование подзапросов, возвращающих множество значений.
- •12.3.1. Использование предложений all, some, any.
- •12.3.2. Использование having и агрегатных функций для вложенных подзапросов.
- •12.4. Внешние соединения.
- •12.5. Union - объединение результатов выполнения нескольких операторов select.
- •12.6. Использование операции сцепления строк.
- •12.7. Работа с разными бд в одном запросе.
- •Контрольные вопросы:
12.3.2. Использование having и агрегатных функций для вложенных подзапросов.
Если в условиях поиска для вложенного запроса нужно указать агрегатную функцию, используется HAVING.
ПРИМЕР
Определить код и среднюю стоимость экземпляра книги, у которой средняя стоимость экземпляра книги больше средней стоимости экземпляров других книг.
SELECT BIN1.BookCode, AVG(BIN1.Cost) AS AvgCost
FROM BookInventaryNumbers BIN1
GROUP BY BIN1.BookCode
HAVING AVG(Cost) >= ALL (SELECT AVG(BIN2.Cost)
FROM BookInventaryNumbers BIN2
GROUP BY BIN2.BookCode)
Обратим внимание на то, что в данном случае псевдонимы таблиц используются не столько для сокращения записей, сколько для определения какие поля брать для работы внешнего и внутреннего операторов SELECT.
Сначала из таблицы BookInventaryNumbers выбирается значения средней стоимости экземпляров всех книг (вложенный подзапрос). Затем из этой же таблицы выбирается код и средняя стоимость экземпляра той книги, которая является наибольшей.
Результат работы оператора приведен в таблице 12.7.
Таблица 12.7.
BookCode |
Cost |
5 |
56,78 |
12.4. Внешние соединения.
Выше нами были рассмотрены внутренние соединения таблиц базы данных. Напомним, что внутренние соединения имеют место, если в предложении WHERE указано условие
<имя столбца таблицы 1> <оператор> <имя столбца таблицы 2>
Существует также и другой вид соединения таблиц, внешнее соединение. Оно определяется в предложении FROM согласно следующей спецификации
SELECT {* | <значение1> [, <значение2> ...]}
FROM <таблица1> <вид соединения> JOIN < таблица2>
ON <условие поиска>
Внешнее соединение похоже на внутреннее соединение, но в результирующий набор данных включаются также записи ведущей таблицы соединения, которые объединяются с пустым множеством записей другой таблицы. Какая из таблиц будет ведущей, определяет вид соединения:
LEFT - (левое внешнее соединение), когда ведущей является таблица1 (расположенная слева от вида соединения);
RIGHT - (правое внешнее соединение), когда ведущей является таблица2.
ПРИМЕР
Пусть имеются две таблицы А и В
Таблица А |
Таблица В |
||||
Столбец Р1 |
Столбец Р2 |
Столбец Р3 |
|
Столбец Р1 |
Столбец Р2 |
a |
x |
400 |
x |
1 |
|
b |
x |
200 |
y |
2 |
|
c |
y |
500 |
z |
2 |
|
d |
|
|
|
|
Тогда выполнение оператора SELECT, реализующее внешнее левое соединение,
SELECT A.P1, A.P2, B.P2
FROM A LEFT JOIN B ON A.P2 = B.P1
Приведет к выдаче такого результирующего набора данных:
Столбец A.Р1 |
Столбец A.Р2 |
Столбец B.Р2 |
a |
x |
1 |
b |
x |
1 |
c |
y |
2 |
d |
|
|
Серым цветом показаны столбцы ведущей таблицы А. Как видно, для записи таблицы А, где столбец А.Р1 имеет значение 'd', нет парных записей в таблице В, для которых удовлетворялось бы условие поиска А.Р2 = В.Р1. Поэтому данная запись таблицы А показана в соединении с пустой записью.
В то же время, выполнение оператора SELECT, реализующего внешнее правое соединение
SELECT A.PI, A.P2, В.Р2
FROM A RIGHT JOIN В ON A.P2 = В.P1
приведет к выдаче такого результирующего набора данных:
Столбец A.Р1 |
Столбец A.Р2 |
Столбец B.Р2 |
a |
x |
1 |
b |
x |
1 |
c |
y |
2 |
|
|
2 |
Пунктиром показаны столбцы ведущей таблицы В. Как видно, для записи таблицы В, где столбец В.Р1 имеет значение 'z' и столбец В.Р2 имеет значение '2', нет парных записей в таблице А, для которых удовлетворялось бы условие поиска А.Р2 = В.Р1. Поэтому данная запись таблицы В показана в соединении с пустой записью.