2008 г.
Базы данных. Вводный курс
Сергей Кузнецов
Назад Содержание Вперёд 19.4.1. Соединенные таблицы
В примерах предыдущей и данной лекций присутствовало много запросов с соединениями двух или более таблиц. Условия соединения задавались предикатами сравнения столбцов таблиц, специфицированных в разделе FROM , и входили в состав логических выражений раздела WHERE (или, реже, раздела HAVING ). Поскольку на практике требуются разные виды соединений, в стандарте SQL/92 появилась альтернативная возможность спецификации соединений – соединенная таблица (joined table ). Соответствующая конструкция может использоваться в разделе FROM выражения запросов и фактически позволяет строить выражения соединений таблиц. Синтаксические правила построения таких выражений выглядят следующим образом:
joined_table ::= cross_join
| qualified_join
| natural_join
| union_join
cross_join ::= table_reference CROSS JOIN table_primary
qualified_join ::= table_reference [ join_type ] JOIN
table_primary join_specification
natural_join ::= table_reference NATURAL [ join_type ]
JOIN table_primary
union_join ::= table_reference UNION JOIN table_primary
join_type ::= INNER | { LEFT | RIGHT | FULL } [ OUTER ]
join_specification ::= ON conditional_expression
| USING (column_comma_list)
Напомним, что синтаксические правила для table_reference и table_primary были показаны в подразделе 17.3.2. Ссылки на таблицы раздела FROM лекции 17.
Как показывает сводка синтаксических правил, в SQL поддерживается много вариантов соединений. Чтобы объяснить особенности разных видов соединений на неформальном уровне, требуется очень большой объем текста с большим числом повторений. Поэтому сначала мы приведем достаточно формальное описание порядка определения заголовка и тела результирующей таблицы для всех разновидностей соединений. Фактически это описание напрямую позаимствовано из стандарта SQL:1999 с некоторыми незначительными упрощениями. Затем мы представим ряд иллюстрирующих примеров.
Формальные определения
Пусть требуется выполнить некоторую операцию соединения над таблицами table1 и table2 . Тогда:
- Обозначим через
CP результат выполнения запроса144)
SELECT *
FROM table1, table2
- Если задается операция
JOIN (или NATURAL JOIN ) без явного указания типа соединения (join_type ), то по умолчанию имеется в виду INNER JOIN (или NATURAL INNER JOIN ). - Если в спецификации соединения (
join_specification ) указано ключевое слово ON , то все ссылки на столбцы, встречающиеся в условном выражении (conditional_expression ), должны указывать на столбцы таблиц table1 и table2 или на столбцы таблиц внешнего запроса. Если в этом условном выражении присутствует вызов агрегатной функции, то соединенная таблица может фигурировать только в подзапросах, используемых в разделах HAVING или SELECT внешнего запроса, и ссылка на столбец в вызове функции должна указывать на столбец таблицы внешнего запроса. - Для прямых соединений (
CROSS JOIN ) и всех других видов соединения, включающих раздел ON , заголовок результата операции совпадает с заголовком таблицы CP . - Если в спецификации вида соединения присутствуют ключевые слова
NATURAL или USING , то заголовок результата операции определяется следующим образом:
- Набор строк результата (множество или мультимножество) определяется по следующим правилам. Обозначим через
T следующие наборы строк:
- если видом соединения является
UNION JOIN , то T – пусто; - если видом соединения является
CROSS JOIN , то T включает все строки, входящие в CP ; - если в спецификацию вида соединения входит раздел
ON , то T включает все строки CP , для которых результатом вычисления условного выражения является true ; - если в спецификацию вида соединения входят разделы
NATURAL или USING , и список SLCC не является пустым, то T включает все строки CP , для которых значения соответствующих столбцов соединения совпадают146); - если в спецификацию вида соединения входят разделы
NATURAL или USING , и список SLCC является пустым, то T включает все строки CP .
- Обозначим через
P1 (P2 ) набор (множество или мультимножество) всех строк таблицы table1 (table2 ), каждая из которых участвует в образовании некой строки T . - Обозначим через
U1 (U2 ) набор (множество или мультимножество) всех строк таблицы table1 (table2 ), ни одна из которых не участвует в образовании какой-либо строки T . - Обозначим через
X1 набор (множество или мультимножество) всех строк, образуемых из строк набора U1 путем добавления справа подстроки из неопределенных значений, содержащей столько неопределенных значений, сколько столбцов содержит таблица table2 . Обозначим через X2 набор (множество или мультимножество) всех строк, образуемых из строк набора U2 путем добавления слева подстроки из неопределенных значений, содержащей столько неопределенных значений, сколько столбцов содержит таблица table1 . - Для соединений вида
CROSS JOIN и INNER JOIN пусть S обозначает тот же набор строк, что и T . - Для соединений вида
LEFT OUTER JOIN пусть S обозначает набор строк, являющийся результатом выражения запросов
SELECT * FROM T
UNION ALL
SELECT * FROM X1;
- Для соединений вида
RIGHT OUTER JOIN пусть S обозначает набор строк, являющийся результатом выражения запросов
SELECT * FROM T
UNION ALL
SELECT * FROM X2;
- Для соединений вида
FULL OUTER JOIN пусть S обозначает набор строк, являющийся результатом выражения запросов
SELECT * FROM T
UNION ALL
SELECT * FROM X1
UNION ALL
SELECT * FROM X2;
- Для соединений вида
UNION JOIN пусть S обозначает набор строк, являющийся результатом выражения запросов
SELECT * FROM X1
UNION ALL
SELECT * FROM X2;
- Если в спецификации вида соединения присутствуют ключевые слова
NATURAL или USING , то результат операции совпадает с результатом выражения запросов
SELECT SLCC, SLT1, SLT2
FROM S;
- Во всех остальных случаях результат операции совпадает с
S .
144 Интересно, что для этого запроса возможна альтернативная формулировка с использованием операции CROSS JOIN: SELECT * FROM table1 CROSS JOIN table2 . Может возникнуть естественный вопрос: зачем вводить специальную конструкцию для декартова произведения? По мнению автора, эта конструкция была введена, главным образом, для повышения уровня общности языка SQL. Кроме того, использование явного ключевого слова CROSS JOIN является подтверждением того, что пользователь действительно может получить декартово произведение, а не упустил по ошибке раздел WHERE .
145 Для удобства читателей напомним, что по определению выражение COALESCE (V1, V2) эквивалентно следующему выражению с переключателем: CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END .
146 Совпадают в строгом смысле, т.е. значение столбца table1 .c совпадает со значением столбца table2.c тогда и только тогда, когда значением операции сравнения table1.c = table2.c является true .
Назад Содержание Вперёд
|
|