При попытке исполнения запроса: CREATE DOMAIN EMP_NO AS INTEGER CHECK (VALUE BETWEEN 1 AND 10000); Выдается ошибка: Неизвестный тип объекта "DOMAIN" в интсрукции CREATE, DROP или ALTER. Используется SQL Server MS SQL 2008R2 |
Группировка и условия раздела HAVING, порождаемые и соединенные таблицы
Примеры соединений разного вида
Основное назначение приводимых ниже примеров состоит не в том, чтобы продемонстрировать практическую значимость разнообразных соединений, а лишь в том, чтобы помочь в них разобраться. 8За очевидностью мы опустим пример CROSS JOIN . Поэтому мы будем использовать упрощенные и формальные таблицы и показывать заголовки и тела результирующих таблиц.
Итак, пусть имеются таблицы table1 (a1, a2, c1, c2) и table2 (b1, b2, c1, c2) со следующими телами:
Обозначим через JR таблицу, являющуюся результатом соединения. Тогда для операции table1 INNER JOIN table2 ON a1=b1 AND a2<b2 ( внутреннее соединение по условию ) тело JR будет следующим:
a1 | a2 | table1.c1 | table1.c2 | b1 | b2 | table2.c1 | table2.c2 |
1 | 1 | 1 | 1 | 1 | 2 | 2 | 3 |
1 | 1 | 2 | 3 | 1 | 2 | 2 | 3 |
1 | 1 | 2 | 3 | 1 | 2 | 2 | 3 |
Строки-дубликаты появились в JR, поскольку в первом операнде присутствовали строки-дубликаты, удовлетворяющие условию соединения.
Результатом операции table1 INNER JOIN table2 USING (c2) ( внутреннее соединение по совпадению значений указанных одноименных столбцов ) будет следующая таблица.
a1 | a2 | table1.c1 | c2 | b1 | b2 | table2.c1 |
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
Результат операции table1 INNER JOIN table2 USING (c1,c2):
Такой же результат будет получен при выполнении операции table1 NATURAL INNER JOIN table2 ( естественное внутреннее соединение ). Более того, для произвольных таблиц table1 и table2 результаты операций table1 INNER JOIN table2 USING (с1, c2, ...cn) и table1 INNER NATURAL JOIN table2 совпадают в том и только в том случае, когда список имен столбцов с1, c2, ... cn включает все имена столбцов, общие для таблиц table1 и table2.
Результатом операции table1 LEFT OUTER JOIN table2 ON a1=b1 AND a2<b2 ( левое внешнее соединение по условию) будет следующая таблица:
a1 | a2 | table1.c1 | table1.c2 | b1 | b2 | table2.c1 | table2.c2 |
1 | 1 | 1 | 1 | 1 | 2 | 2 | 3 |
1 | 1 | 2 | 3 | 1 | 2 | 2 | 3 |
1 | 1 | 2 | 3 | 1 | 2 | 2 | 3 |
2 | 3 | 4 | NULL | NULL | NULL | NULL | NULL |
3 | NULL | NULL | 5 | NULL | NULL | NULL | NULL |
Как видно, в результате левого внешнего соединения сохраняются все данные первого (левого) операнда.
Результатом операции table1 RIGHT OUTER JOIN table2 ON a1=b1 AND a2<b2 ( правое внешнее соединение по условию ) будет следующая таблица:
Как видно, в результате правого внешнего соединения сохраняются все данные второго (правого) операнда.
Результатом операции table1 FULL OUTER JOIN table2 ON a1=b1 AND a2<b2 ( полное внешнее соединение по условию ) будет следующая таблица:
Как видно, в результате полного внешнего соединения сохраняются данные обоих операндов. Кстати, полное внешнее соединение иногда называют еще симметричным внешним соединением. Очевидно, что все операции внутреннего соединения и операция полного внешнего соединения коммутативны, а операции левого и правого соединения коммутативными не являются.
Результатом операции table1 LEFT OUTER JOIN table2 USING (c2) ( левое внешнее соединение по совпадению значений указанных одноименных столбцов >) будет следующая таблица:
a1 | a2 | table1.c1 | c2 | b1 | b2 | table2.c1 |
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
2 | 3 | 4 | NULL | NULL | NULL | NULL |
Результатом операции table1 RIGHT OUTER JOIN table2 USING (c2) ( правое внешнее соединение по совпадению значений указанных одноименных столбцов ) будет следующая таблица:
a1 | a2 | table1.c1 | c2 | b1 | b2 | table2.c1 |
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
1 | 1 | 2 | 3 | 1 | 2 | 2 |
1 | 1 | 2 | 3 | 3 | 3 | 2 |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
3 | NULL | NULL | 5 | 3 | NULL | NULL |
NULL | NULL | NULL | 4 | 4 | 4 | 4 |
Результатом операции table1 FULL OUTER JOIN table2 USING (c2) ( полное внешнее соединение по совпадению значений указанных одноименных столбцов ) будет следующая таблица:
Результатом операции table1 LEFT OUTER JOIN table2 USING (c2, c1) (и операции table1 NATURAL LEFT OUTER JOIN table2 - естественное левое внешнее соединение ) будет следующая таблица:
a1 | a2 | c1 | c2 | b1 | b2 |
1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
2 | 3 | 4 | NULL | NULL | NULL |
3 | NULL | NULL | 5 | NULL | NULL |
Результатом операции table1 RIGHT OUTER JOIN table2 USING (c2, c1) (и операции table1 NATURAL RIGHT OUTER JOIN table2 - естественное правое внешнее соединение ) будет следующая таблица:
a1 | a2 | c1 | c2 | b1 | b2 |
1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
NULL | NULL | 4 | 4 | 4 | 4 |
NULL | NULL | NULL | 5 | 3 | NULL |
NULL | NULL | NULL | 5 | 3 | NULL |
Результатом операции table1 FULL OUTER JOIN table2 USING (c2, c1) (и операции table1 NATURAL FULL OUTER JOIN table2 - естественное полное внешнее соединение ) будет следующая таблица:
a1 | a2 | c1 | c2 | b1 | b2 |
1 | 1 | 1 | 1 | 1 | 1 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
1 | 1 | 2 | 3 | 1 | 2 |
1 | 1 | 2 | 3 | 3 | 3 |
2 | 3 | 4 | NULL | NULL | NULL |
3 | NULL | NULL | 5 | NULL | NULL |
NULL | NULL | 4 | 4 | 4 | 4 |
NULL | NULL | NULL | 5 | 3 | NULL |
NULL | NULL | NULL | 5 | 3 | NULL |
Наконец, результатом операции table1 UNION JOIN table2 ( соединение объединением ) будет следующая таблица:
Примеры запросов с использованием соединенных таблиц
Мы приведем всего пару примеров, чтобы проиллюстрировать формулировки запросов, в разделе FROM которых используются ссылки на соединенные таблицы, т. е. выражения соединений.
SELECT DEPT.DEPT_NO, EMP1.EMP_NAME, COUNT(*), MIN(EMP2.EMP_SAL), MAX(EMP2.EMP_SAL), AVG(EMP2.EMP_SAL) FROM (DEPT NATURAL INNER JOIN EMP AS EMP2) INNER JOIN EMP AS EMP1 ON DEPT.DEPT_MNG = EMP1.EMP_NO GROUP BY DEPT.DEPT_NO, EMP1.EMP_NAME;15.17. Для каждого отдела найти его номер, имя руководителя, число служащих, минимальный, максимальный и средний размеры зарплаты служащих (еще одна формулировка запроса из примера 15.4).
SELECT EMP1.EMP_NO, EMP2.EMP_NAME FROM (EMP AS EMP1 NATURAL INNER JOIN DEPT) INNER JOIN EMP AS EMP2 ON DEPT.DEPT_MNG = EMP2.EMP_NO WHERE EMP1.EMP_SAL > 30000.00;15.18. Найти номера служащих и имена их начальников отделов для служащих, размер зарплаты которых больше 30000 руб.
Можно обойтись вообще без раздела WHERE, если пожертвовать "естественностью" первого соединения ( пример 15.17.1):
SELECT EMP1.EMP_NO, EMP2.EMP_NAME FROM (EMP AS EMP1 INNER JOIN DEPT ON EMP1.DEPT_NO = DEPT.DEPT_NO AND EMP1.EMP_SAL > 30000.00) INNER JOIN EMP AS EMP2 ON DEPT.MNG = EMP2.EMP_NO;15.17.1.
Возможности соединенных таблиц открывают широкий простор для воображения, но не будем увлекаться и ограничимся приведенными простыми примерами.