Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Базы Данных - Сибилев, 2007

.pdf
Скачиваний:
290
Добавлен:
11.05.2015
Размер:
1.93 Mб
Скачать

181

Выполняя селекцию, исполняющая система на каждой строке F-

таблицы вычисляет значение предиката – условия отбора. Если на текущей строке предикат принял значение FALSE или UNKNOWN, то строка уда-

ляется из рабочего буфера. В результате в буфере остаётся W-таблица, со-

держащая те и только те строки операнда, на которых предикат принял значение TRUE.

Пример 1. Получить всю информацию о поставщиках, имеющих статус выше 90.

SELECT *

FROM S

WHERE St > 90;

В результате обработки предложения FROM в рабочем буфере будет создана неименованная таблица, эквивалентная таблице S (см. приложение А).

Snum

Snam

St

Ci

S8

Владимир

 

30 Томск

S2

Николай

50

Асино

 

 

 

 

S5

Константин

100

Яя

 

 

 

 

S4

Петр

20

Рио-де-Жанейро

 

 

 

 

S3

Григорий

80

Яя

 

 

 

 

S9

Егор

100

Яя

 

 

 

 

S7

Сергей

90

Асино

S1

Иван

100

Томск

 

 

 

 

S6

Иван

100

Лесото

 

 

 

 

В процессе обработки предложения будут удалены строки, содержа-

щие в столбце St значения, меньшие или равные 90. Вот результат запро-

са:

Snum

Snam

St

Ci

S5

Константин

100

Яя

S9

Иван

100

Лесото

S9

Егор

100

Яя

S1

Иван

100

Томск

Пример 2. Получить значения номеров и наименований изделий,

производимых в Томске.

182

SELECT Jnum, Jnam

FROM J

WHERE Ci = Томск;

Jnum Jnam

J3

дисплей

J6

клавиатура

Пример 3. Получить значения номеров поставщиков, поставляющих

деталь P1 для изделия J1.

SELECT DISTINCT Snum

FROM SPJ

WHERE Jnum = ‘J1’ AND Pnum = ‘P1’;

SNUM

S8

Пример 4. Получить сведения о поставках, выполненных поставщи-

ками S3, S5, S4, S2.

SELECT *

FROM SPJ

WHERE Snum BETWEEN ‘S2’ AND ‘S5’;

Snum

Pnum

Jnum

Qt

S2

P3

J7

500

S2

P9

J4

200

S3

P4

J8

150

S3

P9

J9

600

S4

P4

J1

130

S5

P3

J8

400

Рассмотрим теперь более сложные запросы, требующие выборки данных из нескольких таблиц.

7.2.8 Соединения таблиц

Соединения таблиц в SQL2 могут быть реализованы двумя способа-

ми:

− путём использования встроенной операции соединения в предло-

жении FROM;

183

− путём явного указания условий соединения в предикате предложе-

ния WHERE.

Здесь мы обсудим встроенные операции соединения, используемые

в предложении FROM19.

соединение ::= перекрёстное_соединение

| естественное_соединение

| соединение_по_именам_столбцов

| соединение_по_условию

| UNION_соединение

Замечание. Любая из перечисленных структур замещает имя табли-

цы в предложении FROM.

Перекрёстное соединение реализует операцию расширенного пря-

мого произведения РА.

перекрёстное_соединение ::=

таблица_А CROSS JOIN таблица_В

Операцию можно применять к любой паре таблиц схемы. Их совмес-

тимость по взятию расширенного прямого произведения достигается за

счёт уточнения имён полей именами таблиц.

Пример. Пусть в нашей учебной БД существуют следующие реали-

зации таблиц P и J:

 

Таблица P (Детали)

Таблица J (Изделия)

Pnum

Pnam

We

Co

Ci

P1

корпус

300

белый

Томск

P3

кнопка

5

красный

Томск

P5

панель

100

серый

Асино

P2

разъём

3

чёрный

Яя

Jnum

Jnam

Ci

J1

процессор

Асино

J6

клавиатура

Томск

J7

мышь

NULL

P CROSS JOIN J (Перекрёстное соединение)

Pnum

Pnam

We

Co

P.Ci

Jnum

Jnam

J.Ci

 

P1

корпус

300

белый

Томск

J1

процессор

Асино

 

P1

корпус

300

белый

Томск

J6

клавиатура

Томск

 

P1

корпус

300

белый

Томск

J7

мышь

NULL

 

P3

кнопка

5

красный

Томск

J1

процессор

Асино

 

 

 

 

 

 

 

 

 

 

19 Стандарт SQL1 не допускал подобных операций.

184

P3

кнопка

5

красный

Томск

J6

клавиатура

Томск

P3

кнопка

5

красный

Томск

J7

мышь

NULL

P5

панель

100

серый

Асино

J1

процессор

Асино

P5

панель

100

серый

Асино

J6

клавиатура

Томск

P5

панель

100

серый

Асино

J7

мышь

NULL

P2

разъём

3

чёрный

Яя

J1

процессор

Асино

P2

разъём

3

чёрный

Яя

J6

клавиатура

Томск

P2

разъём

3

чёрный

Яя

J7

мышь

NULL

Никакого семантического значения этот набор данных не имеет. Как правило, он используется для построения других таблиц. Заметим, что предложения FROM A, B и FROM A CROSS JOIN B эквивалентны, т.е.

производят временные таблицы, совпадающие с точностью до порядка строк.

Операция естественного соединения в SQL может быть реализова-

на в четырёх разновидностях.

естественное_соединение ::=

таблица_А [NATURAL] [тип_соединения] JOIN таб-

лица_В

тип_соединения ::= INNER | {{LEFT | RIGHT | FULL} [OUTER]}

Ключевое слово NATURAL смысловой нагрузки не несёт и может быть опущено. Соединяемые таблицы должны иметь одноимённые столб-

цы одного типа и одинаковой длины.

Естественное соединение может быть внутренним (INNER) или

внешним (OUTER). По умолчанию используется INNER.

Операция INNER JOIN производит аналог естественного соедине-

ния РА. Производная таблица содержит все столбцы операндов. Одно-

имённые столбцы включаются однократно. Строками производной табли-

цы являются объединения таких строк операндов, в которых значения всех

одноимённых столбцов совпадают.

Пример. Получим в условиях предыдущего примера таблицу, со-

держащую сведения о парах деталей и изделий, размещённых в одном и том же городе:

185

P INNER JOIN J (Внутреннее естественное соединение)

Pnum

Pnam

We

Co

Ci

Jnum

Jnam

P5

панель

100

серый

Асино

J1

Процессор

P3

кнопка

5

красный

Томск

J6

Клавиатура

P1

корпус

300

белый

Томск

J6

Клавиатура

В этой таблице отсутствуют сведения о детали P2 и изделии J7, так как описывающие их строки не имеют пар по столбцу Ci в таблицах J и P

соответственно.

Однако в практике применения БД нередко встречаются запросы,

предполагающие отображение всех строк одной таблицы совместно с су-

ществующими парными строками другой. В реляционной алгебре нет опе-

рации, обеспечивающей построение таких запросов.

Пример. Пусть необходимо получить полные сведения обо всех де-

талях и об изделиях, размещенных в тех же городах. Как мы видели, ре-

зультат операции INNER JOIN не содержит всех ожидаемых данных.

Нужная таблица может быть построена с помощью операции внешнего

(OUTER) соединения, например, левого (LEFT).

P LEFT OUTER JOIN J (Левое внешнее соединение)

Pnum

Pnam

We

Co

Ci

Jnum

Jnam

P1

корпус

300

белый

Томск

J6

Клавиатура

P2

разъём

3

чёрный

Яя

NULL

NULL

P3

кнопка

5

красный

Томск

J6

Клавиатура

P5

панель

100

серый

Асино

J1

Процессор

Аналогично этому, все сведения об изделиях и о деталях, размещён-

ных в тех же городах, можно получить с помощью операции правого

(RIGHT) внешнего соединения.

P RIGHT OUTER JOIN J (Правое внешнее соединение)

Pnum

Pnam

We

Co

Ci

Jnum

Jnam

P5

панель

100

серый

Асино

J1

Процессор

P3

кнопка

5

красный

Томск

J6

клавиатура

P1

корпус

300

белый

Томск

J6

клавиатура

NULL

NULL

NULL

NULL

NULL

J7

Мышь

Легко убедиться в том, что один и тот же результат можно получить как с помощью правого, так и с помощью левого внешнего соединения.

186

Например, выражения J RIGHT JOIN P и P LEFT JOIN J определяют эк-

вивалентные таблицы.

Стандарт SQL2 допускает реализацию так называемого полного

(FULL) внешнего соединения, которое можно понимать как теоретико-

множественное объединение левого и правого внешних соединений.

Пример. Пусть нам нужны сведения обо всех деталях и изделиях с указанием пар деталей и изделий, размещенных в одном и том же городе.

Требуемый результат можно получить с помощью следующей операции: P FULL OUTER JOIN J (Полное внешнее соединение)

Pnum

Pnam

We

Co

Ci

Jnum

Jnam

NULL

NULL

NULL

NULL

NULL

J7

Мышь

P1

корпус

300

белый

Томск

J6

Клавиатура

P2

разъём

3

чёрный

Яя

NULL

NULL

P3

кнопка

5

красный

Томск

J6

Клавиатура

P5

панель

100

серый

Асино

J1

Процессор

Приведём алгоритмическое определение операции полного внеш-

него соединения.

1.Вычислить внутреннее соединение.

2.Для каждой строки левой таблицы, если она не представлена во внутреннем соединении, вычислить строку соединения, заполнив столбцы,

соответствующие левой таблице, значениями текущей строки, а столбцы,

соответствующие правой таблице, NULL-значениями.

3. Для каждой строки правой таблицы, если она не представлена во внутреннем соединении, вычислить строку соединения, заполнив столбцы,

соответствующие правой таблице, значениями текущей строки, а столбцы,

соответствующие левой таблице, NULL-значениями.

4.Добавить результаты шагов 2 и 3 к результату шага 4.

5.Определения левого и правого внешних соединений можно полу-

чить из вышеприведённого, опустив шаг 3 или 2 соответственно.

UNION-соединение можно трактовать как реляционную разность [2,

с. 73] полного внешнего и внутреннего соединений. Синтаксис операции следующий:

187

UNION_соединение ::= таблица_А UNION JOIN таблица_В

Пример. Сведения о деталях, размещённых в городах, в которых не

размещено ни одно изделие, и об изделиях, размещённых в городах, в ко-

торых не размещена ни одна деталь, можно получить с помощью следую-

щей операции:

P UNION JOIN J (UNION-соединение)

Pnum

Pnam

We

Co

Ci

Jnum

Jnam

NULL

NULL

NULL

NULL

NULL

J7

мышь

P2

разъём

3

чёрный

Яя

NULL

NULL

Во всех модификациях естественного соединения сравниваются на-

боры значений всех одноимённых столбцов в строках соединяемых таблиц.

В ряде случаев это может привести к недоразумениям.

Пример. Пусть в нашей БД существует следующая таблица, храня-

щая сведения о поставках деталей для изделий:

Таблица SPJ (Поставки)

Snum

Pnum

Jnum

Qt

S1

P1

J6

100

S1

P2

J6

1877

 

 

 

 

и пусть нам нужны сведения о конкретных деталях, поставляемых для конкретных изделий. Если мы для получения этих сведений используем естественное соединение таблиц P, J и SPJ, то результатом будет следую-

щая таблица:

P INNER JOIN J INNER JOIN SPJ

Pnum

Pnam

We

Co

Ci

Jnum

Jn

Snum

Qt

P1

корпус

300

белый

Томск

J6

клавиатура

S1

100

Результат не содержит всех ожидаемых сведений. Утрачены данные о поставке детали P2. Это произошло потому, что соединения выполнялись по столбцам Pnum, Jnum, Ci. На самом деле соединение по столбцу Ci не нужно.

188

Операция соединения по именам столбцов использует в качестве аргумента список имён столбцов, по которым должно выполняться соеди-

нение.

соединение_по_именам_столбцов ::=

таблица_А [тип_соединения] JOIN таблица_В

USING (имя_столбца.,..)

Как и естественное соединение, эта операция применяется к табли-

цам, имеющим одноимённые столбцы одного типа и одинаковой длины.

Однако соединение выполняется по признаку совпадения значений под-

множества одноимённых столбцов, указанного списком после ключевого слова USING. Допустимы все определённые выше типы соединения.

Пример. В условиях предыдущего примера правильное выражение соединения может быть таким:

(P INNER JOIN SPJ) INNER JOIN J USING (Jnum)

или таким:

P INNER JOIN (SPJ INNER JOIN J) USING (Pnum)

Эти выражения произведут таблицу, эквивалентную показаной ниже.

Pnum

Pnam

We

Co

P.Ci

Snum

Jnum

Qt

Jn

J.Ci

 

 

 

 

 

 

 

 

 

 

P1

корпус

300

белый

Томск

S1

J6

100

Клавиатура

Томск

 

 

 

 

 

 

 

 

 

 

P2

разъём

3

чёрный

Яя

S1

J6

1877

Клавиатура

Томск

 

 

 

 

 

 

 

 

 

 

Операция соединения по условию использует следующий синтак-

сис:

соединение_по_условию ::=

таблица_А [тип_соединения] JOIN таблица_В

ON предикат

предикат – логическое выражение, содержащее ссылки на столбцы соединяемых таблиц и принимающее значения TRUE, FALSE или

UNKNOWN (см. п. 7.2.6). Значение предиката вычисляется на значениях

189

ссылочных столбцов в строке расширенного прямого произведения таблиц

(строке-кандидате соединения).

Соединяемые таблицы должны иметь сравнимые столбцы. Произво-

димая таблица включает все столбцы обоих операндов, а состав её строк зависит от типа соединения.

Внутреннее (INNER) соединение можно рассматривать как реализа-

цию операции соединения по условию РА. Оно производит только такие конкатенации строк операндов, на которых предикат принимает значение

TRUE.

Пример. Для того чтобы получить сведения о деталях и изделиях,

размещённых в различных городах, следует использовать операцию внут-

реннего соединения по условию P.Ci <> J.Ci: P INNER JOIN J ON P.Ci <> J.Ci

Pnum

Pnam

We

Co

P.Ci

Jnum

Jn

J.Ci

P1

корпус

300

белый

Томск

J1

процессор

Асино

P2

разъём

3

чёрный

Яя

J1

процессор

Асино

P3

кнопка

5

красный

Томск

J1

процессор

Асино

P2

разъём

3

чёрный

Яя

J6

клавиатура

Томск

P5

панель

100

серый

Асино

J6

клавиатура

Томск

Определения внешних соединений по условию аналогичны опреде-

лениям естественных внешних соединений. Сформулируйте их самостоя-

тельно.

Читатель легко убедится в том, что в условиях рассматриваемого примера соединение P LEFT JOIN J ON P.Ci <> J.Ci совпадает с внутрен-

ним. Соединение P RIGHT JOIN J ON P.Ci <> J.Ci будет содержать до-

полнительную строку – сведения об изделии J7.

Понятие соединения в SQL2 шире аналогичного понятия в классиче-

ской реляционной алгебре. Определяя внешние соединения и соединения

USING и UNION, авторы стандарта руководствовались потребностями практического применения языка. Действительно, как мы увидим далее,

190

использование встроенных операторов соединения позволяет значительно упростить логику запросов на выборку данных.

7.2.9 Запросы с соединениями таблиц

В общем случае первые три предложения оператора выборки данных выполняют комбинацию операций соединения, селекции и проекции20.

Многие распространённые в настоящее время программные продук-

ты не поддерживают встроенные операции соединения. Входные языки этих СУБД обеспечивают возможность указания соответствующих усло-

вий в предикате предложения WHERE. Однако наиболее «продвинутые» системы допускают оба варианта определения соединений. В нижесле-

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

Пример 1. Получить значения наименований изделий, для которых выполняет поставки поставщик S1.

Источником данных для этого запроса служат таблицы J и SPJ. Все-

гда можно использовать, по меньшей мере, два подхода к проектированию оператора выборки.

Встиле РИ: «Получить значения атрибута Jnam из таких кортежей отношения J, для которых в отношении SPJ существуют кортежи с теми же значениями атрибута Jnum и значениями атрибута Snum, равными S1.»

Встиле РА: «Выполнить проекцию на атрибут Jnam селекции по условию Snum = ‘S1’ естественного соединения таблиц J и SPJ.»

Первый (возможно, наиболее естественный) подход мы рассмотрим в п. 7.2.12.

Второй подход приводит к следующим сответствующим SQL2 фор-

мулировкам:

Вариант 1

SELECT DISTINCT Jnam

20 Иногда эту последовательность операций называют операцией отображения.