Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базы данных Шехтман.doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
2.7 Mб
Скачать

6.6. Вложенные запросы

Можно вкладывать запросы друг в друга. Внутренний запрос генерирует значение, которое проверяется в предикате внешнего запроса (WHERE, HAVING). Для организации вложенных запросов можно применять синонимы.

1. Список тех, кто сдал все положенные экзамены:

SELECT a.FIO FROM R1 a

WHERE a.O>2

GROUP BY a.FIO

HAVING COUNT(*) =

(SELECT COUNT(*) FROM R2, R3

WHERE R2.G = R3.G AND R2.FIO = a.FIO)

Вложенный запрос – количество экзаменов, которое надо сдать. Оно сравнивается с фактическим количеством сданных экзаменов.

Можно применять оператор EXISTS, который принимает значение TRUE только если результат вложенного запроса не пуст:

2. Список тех, кто должен сдавать экзамен по ‘Базам Данных’, но еще не сдавал:

SELECT FIO FROM R2 a, R3 WHERE R2.G = R3.G AND D = 'БД '

AND NOT EXISTS

(SELECT FIO FROM R1 WHERE FIO=a.FIO AND D= ‘БД')

Для определения того факта, что каждый из выбранных в подзапросе кортежей удовлетворяет условию, следует использовать оператор ALL:

3. Все, кто сдал не ниже 4 по всем дисциплинам:

SELECT DISTINCT R1.FIO FROM R1 WHERE 4 <=

ALL (SELECT a.O FROM R1 AS a WHERE R1.FIO = a.FIO)

Кроме того, существует и оператор ANY, который принимает значение TRUE при условии, что хотя бы один кортеж из подзапроса удовлетворяет условию.

6.7. Внешние объединения

SQL92 расширил понятие условного соединения. В SQL89 использовались только соединения, выражаемые через FROM и WHERE: в результирующее отношение попадают только сцепленные по заданным условиям кортежи исходных отношений. Однако на практике необходимо объединять таблицы так, чтобы в результирующее отношение попали все строки первой таблицы, а вместо тех строк второй таблицы, для которых не выполнено условие соединения, в результирующее отношение попадали бы неопределенные значения. Или наоборот, включаются все строки второй таблицы, а отсутствующие строки из первой таблицы дополняются неопределенными значениями. Такие соединения называются внешними, соответственно левыми или правыми. Старые условные соединения получили название - внутренние.

Новый синтаксис оператора SELECT (в части FROM):

FROM <cписок таблиц>|

<выражение естественного соединения>|

<выражение соединения>|

<список таблиц> ::= <имя таблицы> [синоним таблицы] […] [<,имя таблицы> [синоним таблицы]]

<выражение естественного соединения> ::= <имя таблицы 1> NATURAL {INNER| FULL [OUTER]]| LEFT [OUTER] | RIGHT [OUTER]} JOIN <имя таблицы 2>

<выражение соединения> ::= <имя таблицы 1> {INNER | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER]} JOIN {ON условие | [USING (список столбцов)] } <имя таблицы 2>

1. Все оценки всех студентов по всем экзаменам, которые они должны были сдавать (если не сдали, то NULL):

SELECT R1.FIO, R1.D, R1.O

FROM (R2 NATURAL JOIN R3) LEFT JOIN R1 USING (FIO,D)

Для иллюстрации отличий между внутренними и внешними соединениями используем следующий набор отношений:

R1 = (Код_товара, Имя_товара)

R2 = (Код_поставщика, Имя_поставщика)

R3 = (Код_товара, Код_поставщика, Кол-во_товара)

Перечислить количество товаров, их имена и их поставщиков:

2. Внутреннее соединение (старый синтаксис):

SELECT R3.Кол-во_товара, R1.Имя_товара, R2.Имя_поставщика

FROM R3, R1, R2

WHERE R3.Код_товара = R1.Код_товара AND

R3.Код_поставщика = R2.Код_поставщика

3. Внутреннее соединение (новый синтаксис):

SELECT R3.Кол-во_товара, R1.Имя_товара, R2.Имя_поставщика

FROM (R3 INNER JOIN R1 ON R3.Код_товара = R1.Код_товара)

INNER JOIN R2 ON R3.Код_поставщика = R2.Код_поставщика

4. Левое внешнее соединение:

SELECT R3.Кол-во_товара, R1.Имя_товара, R2.Имя_поставщика

FROM (R1 LEFT JOIN R3 ON R3.Код_товара = R1.Код_товара)

LEFT JOIN R2 ON R3.Код_поставщика = R2.Код_поставщика

В отличие от запросов 2 и 3, результат этого запроса попадут и те товары, которые ни разу не поставлялись ни одним поставщиком, но присутствуют в “справочнике товаров” R1. Для таких товаров поля Имя_товара и Имя_поставщика будут содержать пустые значения.