Опубликован: 10.10.2005 | Уровень: специалист | Доступ: платный | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 5:

Группировка и условия раздела HAVING, порождаемые и соединенные таблицы

Более сложные конструкции оператора выборки

В этом разделе мы обсудим возможности языка SQL, касающиеся явного задания выражений с соединениями и порождаемых таблиц с горизонтальной связью (lateral_derived_table). Начнем с соединений.

Соединенные таблицы

В примерах предыдущей и данной лекций присутствовало много запросов с соединениями двух или более таблиц. Условия соединения задавались предикатами сравнения столбцов таблиц, специфицированных в разделе 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 были показаны в лекции 13.

Как показывает сводка синтаксических правил, в SQL поддерживается много вариантов соединений. Чтобы объяснить особенности разных видов соединений на неформальном уровне, требуется очень большой объем текста с большим числом повторений. Поэтому сначала мы приведем достаточно формальное описание порядка определения заголовка и тела результирующей таблицы для всех разновидностей соединений. Фактически это описание напрямую позаимствовано из стандарта SQL:1999 с некоторыми незначительными упрощениями. Затем мы представим ряд иллюстрирующих примеров.

Формальные определения

Пусть требуется выполнить некоторую операцию соединения над таблицами table1 и table2. Тогда:

  • Обозначим через CP результат выполнения запроса5Интересно, что для этого запроса возможна альтернативная формулировка с использованием операции CROSS JOIN: SELECT * FROM table1 CROSS JOIN table2. Может возникнуть естественный вопрос: зачем вводить специальную конструкцию для декартова произведения? По мнению автора, эта конструкция была введена, главным образом, для повышения уровня общности языка SQL. Кроме того, использование явного ключевого слова CROSS JOIN является подтверждением того, что пользователь действительно может получить декартово произведение, а не упустил по ошибке раздел WHERE .
    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, то заголовок результата операции определяется следующим образом:
    • если в спецификации вида соединения присутствует ключевое слово NATURAL, то будем называть соответствующими столбцами соединения ( corresponding join column ) все столбцы таблиц table1 и table2, которые имеют в заголовках этих таблиц одинаковые имена. Если в спецификации вида соединения присутствует ключевое слово USING, то будем называть соответствующими столбцами соединения ( corresponding join column ) все столбцы таблиц table1 и table2, имена которых входят в список имен столбцов раздела USING (эти столбцы должны быть одноименными в заголовках обеих таблиц). В обоих случаях типы данных каждой пары соответствующих столбцов должны быть совместимыми;
    • будем называть списком выборки соответствующих столбцов соединения ( select_list of corresponding join columns - SLCC ) список элементов вида COALESCE (table1.c, table2.c) AS c*, где с6Для удобства читателей напомним, что по определению выражение COALESCE (V1, V2) эквивалентно следующему выражению с переключателем: CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END . является именем соответствующего столбца соединения. Элементы располагаются в том порядке, в котором они появляются в заголовке таблицы table1. Обозначим через SLT1 ( SLT2 ) список имен столбцов таблицы table1 ( table2 ), которые не являются соответствующими столбцами соединения. Имена располагаются в том же порядке, в котором они появляются в заголовке соответствующей таблицы;
    • заголовок результата совпадает с заголовком результата запроса
      SELECT SLCC, SLT1, SLT2
      FROM table1, table2;
  • Набор строк результата (множество или мультимножество) определяется по следующим правилам. Обозначим через T следующие наборы строк:
    • если видом соединения является UNION JOIN, то T - пусто;
    • если видом соединения является CROSS JOIN, то T включает все строки, входящие в CP ;
    • если в спецификацию вида соединения входит раздел ON, то T включает все строки CP, для которых результатом вычисления условного выражения является true ;
    • если в спецификацию вида соединения входят разделы NATURAL или USING, и список SLCC не является пустым, то T включает все строки CP, для которых значения соответствующих столбцов соединения совпадают7Совпадают в строгом смысле, т.е. значение столбца table1.c совпадает со значением столбца table2.c тогда и только тогда, когда значением операции сравнения table1.c = table2.c является true . ;
    • если в спецификацию вида соединения входят разделы 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.
Алексей Ковтун
Алексей Ковтун

При попытке исполнения запроса:

CREATE DOMAIN EMP_NO AS INTEGER

    CHECK (VALUE BETWEEN 1 AND 10000);

Выдается ошибка: Неизвестный тип объекта "DOMAIN" в интсрукции CREATE, DROP или ALTER. 

Используется SQL Server MS SQL 2008R2

Александра Каева
Александра Каева