Присоединиться (SQL) - Join (SQL)

Предложение соединения в SQL - соответствующее операции соединения в реляционной алгебре - объединяет столбцы из одной или нескольких таблиц в новую таблицу. ANSI -эталонных пять SQL для задают типов JOIN: INNER, LEFT OUTER, RIGHT OUTER, FULL OUTERи CROSS.

Примеры таблиц

Для объяснения типов соединений в остальной части этой статьи используются следующие таблицы:

Таблица сотрудников
Фамилия DepartmentID
Рафферти 31 год
Джонс 33
Гейзенберг 33
Робинсон 34
Смит 34
Уильямс NULL
Таблица отдела
DepartmentID Название отдела
31 год Продажи
33 Инженерное дело
34 Канцелярский
35 год Маркетинг

Department.DepartmentIDявляется первичным ключом из Departmentтаблицы, в то время как Employee.DepartmentIDэто внешний ключ .

Отметим, что в Employee«Вильямс» еще не закреплен за отделом. Также в отдел «Маркетинг» не закреплены сотрудники.

Это оператор SQL для создания приведенных выше таблиц:

CREATE TABLE department(
    DepartmentID INT PRIMARY KEY NOT NULL,
    DepartmentName VARCHAR(20)
);

CREATE TABLE employee (
    LastName VARCHAR(20),
    DepartmentID INT REFERENCES department(DepartmentID)
);

INSERT INTO department
VALUES (31, 'Sales'),
       (33, 'Engineering'),
       (34, 'Clerical'),
       (35, 'Marketing');

INSERT INTO employee
VALUES ('Rafferty', 31),
       ('Jones', 33),
       ('Heisenberg', 33),
       ('Robinson', 34),
       ('Smith', 34),
       ('Williams', NULL);

Перекрестное соединение

CROSS JOINвозвращает декартово произведение строк из таблиц в объединении. Другими словами, он будет создавать строки, которые объединяют каждую строку из первой таблицы с каждой строкой из второй таблицы.

Employee.LastName Employee.DepartmentID Department.DepartmentName Department.DepartmentID
Рафферти 31 год Продажи 31 год
Джонс 33 Продажи 31 год
Гейзенберг 33 Продажи 31 год
Смит 34 Продажи 31 год
Робинсон 34 Продажи 31 год
Уильямс NULL Продажи 31 год
Рафферти 31 год Инженерное дело 33
Джонс 33 Инженерное дело 33
Гейзенберг 33 Инженерное дело 33
Смит 34 Инженерное дело 33
Робинсон 34 Инженерное дело 33
Уильямс NULL Инженерное дело 33
Рафферти 31 год Канцелярский 34
Джонс 33 Канцелярский 34
Гейзенберг 33 Канцелярский 34
Смит 34 Канцелярский 34
Робинсон 34 Канцелярский 34
Уильямс NULL Канцелярский 34
Рафферти 31 год Маркетинг 35 год
Джонс 33 Маркетинг 35 год
Гейзенберг 33 Маркетинг 35 год
Смит 34 Маркетинг 35 год
Робинсон 34 Маркетинг 35 год
Уильямс NULL Маркетинг 35 год


Пример явного перекрестного соединения:

SELECT *
FROM employee CROSS JOIN department;

Пример неявного перекрестного соединения:

SELECT *
FROM employee, department;

Перекрестное соединение можно заменить внутренним соединением с условием Always-true:

SELECT *
FROM employee INNER JOIN department ON 1=1;

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

В стандарте SQL: 2011 перекрестные соединения являются частью необязательного пакета F401 «Расширенная объединенная таблица».

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

Внутреннее соединение

Внутреннее соединение требует , чтобы каждая строки в двух соединяемых таблицах , чтобы иметь соответствующие значения столбцов, и обычно используются присоединиться к операции в приложениях , но не следует считать лучшим выбором во всех ситуациях. Внутреннее соединение создает новую таблицу результатов путем объединения значений столбцов двух таблиц (A и B) на основе предиката соединения. Запрос сравнивает каждую строку A с каждой строкой B, чтобы найти все пары строк, которые удовлетворяют предикату соединения. Когда предикат соединения удовлетворяется путем сопоставления значений, отличных от NULL, значения столбцов для каждой сопоставленной пары строк A и B объединяются в строку результата.

Результат объединения может быть определен как результат первого использования декартова произведения (или перекрестного соединения ) всех строк в таблицах (объединение каждой строки в таблице A с каждой строкой в ​​таблице B) и последующего возврата всех строк, удовлетворяющих требованиям присоединиться к предикату. В реальных реализациях SQL обычно используются другие подходы, такие как хэш-соединения или объединения сортировка-слияние , поскольку вычисление декартова произведения происходит медленнее и часто требует для хранения недопустимо большого количества памяти.

SQL определяет два разных синтаксических способа выражения объединений: «явную нотацию соединения» и «неявную нотацию соединения». «Нотация неявного соединения» больше не считается лучшей практикой, хотя системы баз данных все еще поддерживают ее.

«Явная нотация соединения» использует JOINключевое слово, которому может предшествовать INNERключевое слово, чтобы указать таблицу для соединения, и ONключевое слово, чтобы указать предикаты для соединения, как в следующем примере:

SELECT employee.LastName, employee.DepartmentID, department.DepartmentName 
FROM employee 
INNER JOIN department ON
employee.DepartmentID = department.DepartmentID;
Employee.LastName Employee.DepartmentID Department.DepartmentName
Робинсон 34 Канцелярский
Джонс 33 Инженерное дело
Смит 34 Канцелярский
Гейзенберг 33 Инженерное дело
Рафферти 31 год Продажи

«Нотация неявного соединения» просто перечисляет таблицы для соединения в FROMпредложении SELECTоператора, используя запятые для их разделения. Таким образом, он определяет перекрестное соединение , и в WHEREпредложении могут применяться дополнительные предикаты фильтра (которые работают аналогично предикатам соединения в явной нотации).

Следующий пример эквивалентен предыдущему, но на этот раз с использованием неявной нотации соединения:

SELECT employee.LastName, employee.DepartmentID, department.DepartmentName 
FROM employee, department
WHERE employee.DepartmentID = department.DepartmentID;

Запросы, приведенные в приведенных выше примерах, будут соединяться с таблицами Employee и Department с использованием столбца DepartmentID обеих таблиц. Если DepartmentID этих таблиц совпадает (т. Е. Выполняется предикат соединения), запрос объединит столбцы LastName , DepartmentID и DepartmentName из двух таблиц в строку результатов. Если DepartmentID не совпадает, строка результатов не создается.

Таким образом, результатом выполнения вышеуказанного запроса будет:

Employee.LastName Employee.DepartmentID Department.DepartmentName
Робинсон 34 Канцелярский
Джонс 33 Инженерное дело
Смит 34 Канцелярский
Гейзенберг 33 Инженерное дело
Рафферти 31 год Продажи

Сотрудник «Вильямс» и отдел «Маркетинг» не отображаются в результатах выполнения запроса. Ни у одного из них нет совпадающих строк в другой соответствующей таблице: «Williams» не имеет связанного отдела, и ни один сотрудник не имеет идентификатора отдела 35 («Маркетинг»). В зависимости от желаемых результатов такое поведение может быть небольшой ошибкой, которой можно избежать, заменив внутреннее соединение внешним соединением .

Внутреннее соединение и значения NULL

Программисты должны проявлять особую осторожность при объединении таблиц в столбцы, которые могут содержать значения NULL , поскольку NULL никогда не будет соответствовать никакому другому значению (даже самому NULL), если только условие соединения явно не использует предикат комбинации, который сначала проверяет, что столбцы объединения NOT NULLперед применением оставшееся условие (а) предиката. Внутреннее соединение можно безопасно использовать только в базе данных, которая обеспечивает ссылочную целостность или где столбцы соединения гарантированно не имеют значения NULL. Многие реляционные базы данных для обработки транзакций полагаются на стандарты обновления данных атомарности, согласованности, изоляции и долговечности (ACID), чтобы гарантировать целостность данных, делая внутренние соединения правильным выбором. Однако базы данных транзакций обычно также имеют желательные столбцы соединения, которым разрешено иметь значение NULL. Во многих отчетных реляционных базах данных и хранилищах данных используются большие объемы пакетных обновлений извлечения, преобразования, загрузки (ETL), которые затрудняют или делают невозможным применение ссылочной целостности, что приводит к потенциально NULL-столбцам соединения, которые автор SQL-запроса не может изменить и из-за чего внутренние соединения пропускаются. данные без указания на ошибку. Выбор использования внутреннего соединения зависит от дизайна базы данных и характеристик данных. Левое внешнее соединение обычно может быть заменено внутренним соединением, когда столбцы соединения в одной таблице могут содержать значения NULL.

Любой столбец данных, который может иметь значение NULL (пустой), никогда не должен использоваться в качестве ссылки во внутреннем соединении, если только предполагаемый результат не состоит в том, чтобы исключить строки со значением NULL. Если столбцы соединения NULL должны быть намеренно удалены из набора результатов , внутреннее соединение может быть быстрее, чем внешнее соединение, потому что соединение таблицы и фильтрация выполняются за один шаг. И наоборот, внутреннее соединение может привести к катастрофически низкой производительности или даже к сбою сервера при использовании в запросе большого объема в сочетании с функциями базы данных в предложении SQL Where. Функция в предложении SQL Where может привести к игнорированию базой данных относительно компактных индексов таблиц. База данных может считывать выбранные столбцы из обеих таблиц и объединять их внутри перед уменьшением количества строк с помощью фильтра, который зависит от вычисленного значения, что приводит к относительно огромному объему неэффективной обработки.

Когда набор результатов создается путем объединения нескольких таблиц, включая главные таблицы, используемые для поиска полнотекстовых описаний кодов числовых идентификаторов ( таблица поиска ), значение NULL в любом из внешних ключей может привести к удалению всей строки из набора результатов без указания ошибки. Сложный SQL-запрос, который включает одно или несколько внутренних соединений и несколько внешних соединений, имеет такой же риск для значений NULL во внутренних столбцах ссылки соединения.

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

Можно также классифицировать внутренние соединения как равные соединения, как естественные соединения или как перекрестные соединения.

Equi-join

Равностепенный присоединиться тип конкретного компаратора на основе соединения, которая использует только равенство сравнение в джойне-предикату. Использование других операторов сравнения (таких как <) дисквалифицирует соединение как равное соединение. Запрос, показанный выше, уже предоставил пример равного соединения:

SELECT *
FROM employee JOIN department
  ON employee.DepartmentID = department.DepartmentID;

Мы можем написать equi-join, как показано ниже,

SELECT *
FROM employee, department
WHERE employee.DepartmentID = department.DepartmentID;

Если столбцы в равном объединении имеют одно и то же имя, SQL-92 предоставляет необязательную сокращенную запись для выражения равных объединений посредством USINGконструкции:

SELECT *
FROM employee INNER JOIN department USING (DepartmentID);

Однако эта USINGконструкция - больше, чем просто синтаксический сахар , поскольку набор результатов отличается от набора результатов версии с явным предикатом. В частности, любые столбцы, упомянутые в USINGсписке, будут отображаться только один раз с неполным именем, а не один раз для каждой таблицы в объединении. В приведенном выше случае будет один DepartmentIDстолбец и нет employee.DepartmentIDили department.DepartmentID.

Предложение USINGне поддерживается MS SQL Server и Sybase.

Естественное соединение

Естественное соединение - это частный случай равносоединения. Естественное соединение (⋈) - это бинарный оператор, который записывается как ( RS ), где R и S - отношения . Результатом естественного соединения является набор всех комбинаций кортежей в R и S , которые равны по своим общим именам атрибутов. В качестве примера рассмотрим таблицы Employee и Dept и их естественное соединение:

Работник
Имя EmpId DeptName
Гарри 3415 Финансы
Салли 2241 Продажи
Георгий 3401 Финансы
Харриет 2202 Продажи
Отдел
DeptName Менеджер
Финансы Георгий
Продажи Харриет
Производство Чарльз
 Отдел сотрудников 
Имя EmpId DeptName Менеджер
Гарри 3415 Финансы Георгий
Салли 2241 Продажи Харриет
Георгий 3401 Финансы Георгий
Харриет 2202 Продажи Харриет

Это также можно использовать для определения состава отношений . Например, состав Employee и Dept - это их соединение, как показано выше, спроецированное на все, кроме общего атрибута DeptName . В теории категорий объединение - это и есть волокнистый продукт .

Естественное соединение, возможно, является одним из наиболее важных операторов, поскольку оно является реляционным аналогом логического И. Обратите внимание, что если одна и та же переменная появляется в каждом из двух предикатов, связанных оператором AND, то эта переменная обозначает одно и то же, и оба появления всегда должны быть заменены одним и тем же значением. В частности, естественное соединение позволяет комбинировать отношения, связанные внешним ключом . Например, в приведенном выше примере внешний ключ, вероятно, принадлежит сотруднику . DEPTNAME в МЭИ . DeptName, а затем естественное соединение Employee и Dept объединяет всех сотрудников с их отделами. Это работает, потому что внешний ключ хранится между атрибутами с одинаковыми именами. Если это не так , такие как во внешнем ключе из МЭИ . от менеджера к сотруднику . Назовите, тогда эти столбцы должны быть переименованы до того, как будет выполнено естественное соединение. Такое соединение иногда также называют равным соединением .

Более формально семантика естественного соединения определяется следующим образом:

,

где Fun - это предикат , истинный для отношения r тогда и только тогда, когда r - функция. Обычно требуется, чтобы R и S имели хотя бы один общий атрибут, но если это ограничение опущено, а R и S не имеют общих атрибутов, то естественное соединение становится в точности декартовым произведением.

Естественное соединение можно смоделировать с помощью примитивов Кодда следующим образом. Пусть с 1 , ..., с т быть имена атрибутов , общие для R и S , R 1 , ..., г п быть имена атрибутов уникальны для R и пусть s 1 , ..., s к быть уникальным для атрибутов S . Кроме того, предположим , что имена атрибутов х 1 , ..., х м не являются ни в R , ни в S . На первом этапе имена общих атрибутов в S теперь можно переименовать:

Затем мы берем декартово произведение и выбираем кортежи, которые нужно объединить:

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

Большинство экспертов согласны с тем, что NATURAL JOIN опасны, и поэтому настоятельно не рекомендуют их использовать. Опасность возникает из-за непреднамеренного добавления нового столбца с таким же именем, как у другого столбца в другой таблице. Существующее естественное соединение может затем «естественным образом» использовать новый столбец для сравнений, делая сравнения / совпадения с использованием других критериев (из разных столбцов), чем раньше. Таким образом, существующий запрос может дать разные результаты, даже если данные в таблицах не были изменены, а только увеличены. Использование имен столбцов для автоматического определения ссылок на таблицы не является вариантом в больших базах данных с сотнями или тысячами таблиц, где это наложило бы нереалистичное ограничение на соглашения об именах. Реальные базы данных обычно разрабатываются с данными внешнего ключа, которые не заполняются последовательно (разрешены значения NULL) из-за бизнес-правил и контекста. Обычной практикой является изменение имен столбцов схожих данных в разных таблицах, и это отсутствие жесткой согласованности превращает естественные объединения в теоретическую концепцию для обсуждения.

Вышеупомянутый пример запроса для внутренних объединений может быть выражен как естественное соединение следующим образом:

SELECT *
FROM employee NATURAL JOIN department;

Как и в случае явного USINGпредложения, в объединенной таблице присутствует только один столбец DepartmentID без квалификатора:

DepartmentID Employee.LastName Department.DepartmentName
34 Смит Канцелярский
33 Джонс Инженерное дело
34 Робинсон Канцелярский
33 Гейзенберг Инженерное дело
31 год Рафферти Продажи

PostgreSQL, MySQL и Oracle поддерживают естественные объединения; Microsoft T-SQL и IBM DB2 этого не делают. Столбцы, используемые в объединении, являются неявными, поэтому код объединения не показывает, какие столбцы ожидаются, а изменение имен столбцов может изменить результаты. В стандарте SQL: 2011 естественные объединения являются частью необязательного пакета F401 «Расширенная объединенная таблица».

Во многих средах баз данных имена столбцов контролируются внешним поставщиком, а не разработчиком запросов. Естественное соединение предполагает стабильность и согласованность имен столбцов, которые могут изменяться во время обновлений версии, требуемых поставщиком.

Внешнее соединение

В объединенной таблице сохраняется каждая строка, даже если другой соответствующей строки не существует. Внешние соединения подразделяются на левые внешние соединения, правые внешние соединения и полные внешние соединения, в зависимости от того, какие строки таблицы сохраняются: левая, правая или обе (в данном случае левая и правая относятся к двум сторонам JOINключевого слова). Подобно внутренним соединениям , можно дополнительно подразделить все типы внешних соединений на равные соединения , естественные соединения , ( θ -соединения ) и т. Д. ON <predicate>

В стандартном SQL не существует неявной нотации для внешних соединений.

Диаграмма Венна, показывающая левый кружок и перекрывающуюся часть с заливкой.
Диаграмма Венна, представляющая оператор SQL Left Join между таблицами A и B.

Левое внешнее соединение

Результат левого внешнего соединения (или просто левого соединения ) для таблиц A и B всегда содержит все строки «левой» таблицы (A), даже если условие соединения не находит ни одной совпадающей строки в «правой» таблице. (В). Это означает, что если ONпредложение соответствует 0 (нулю) строк в B (для данной строки в A), соединение все равно вернет строку в результате (для этой строки), но с NULL в каждом столбце из B. A слева. внешнее соединение возвращает все значения из внутреннего соединения плюс все значения в левой таблице, которые не соответствуют правой таблице, включая строки со значениями NULL (пустыми) в столбце ссылки.

Например, это позволяет нам найти отдел сотрудника, но по-прежнему показывает сотрудников, которые не были назначены в отдел (в отличие от приведенного выше примера внутреннего соединения, где неназначенные сотрудники были исключены из результата).

Пример левого внешнего соединения ( OUTERключевое слово необязательно) с дополнительной строкой результатов (по сравнению с внутренним соединением), выделенной курсивом:

SELECT *
FROM employee 
LEFT OUTER JOIN department ON employee.DepartmentID = department.DepartmentID;
Employee.LastName Employee.DepartmentID Department.DepartmentName Department.DepartmentID
Джонс 33 Инженерное дело 33
Рафферти 31 год Продажи 31 год
Робинсон 34 Канцелярский 34
Смит 34 Канцелярский 34
Уильямс NULL NULL NULL
Гейзенберг 33 Инженерное дело 33

Альтернативные синтаксисы

Oracle поддерживает устаревший синтаксис:

SELECT *
FROM employee, department
WHERE employee.DepartmentID = department.DepartmentID(+)

Sybase поддерживает синтаксис ( Microsoft SQL Server не поддерживает этот синтаксис с версии 2000):

SELECT *
FROM employee, department
WHERE employee.DepartmentID *= department.DepartmentID

IBM Informix поддерживает синтаксис:

SELECT *
FROM employee, OUTER department
WHERE employee.DepartmentID = department.DepartmentID
Диаграмма Венна показывает правый круг и перекрывающиеся части с заливкой.
Диаграмма Венна, представляющая SQL-оператор Right Join между таблицами A и B.

Правое внешнее соединение

Правое внешнее объединение (или право присоединиться ) близко напоминает левое внешнее соединение, за исключением лечения таблиц вспять. Каждая строка из «правой» таблицы (B) появится в объединенной таблице хотя бы один раз. Если подходящей строки из «левой» таблицы (A) не существует, NULL появится в столбцах из A для тех строк, которые не совпадают в B.

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

Ниже приведен пример правого внешнего соединения ( OUTERключевое слово необязательно) с дополнительной строкой результатов, выделенной курсивом:

SELECT *
FROM employee RIGHT OUTER JOIN department
  ON employee.DepartmentID = department.DepartmentID;
Employee.LastName Employee.DepartmentID Department.DepartmentName Department.DepartmentID
Смит 34 Канцелярский 34
Джонс 33 Инженерное дело 33
Робинсон 34 Канцелярский 34
Гейзенберг 33 Инженерное дело 33
Рафферти 31 год Продажи 31 год
NULL NULL Маркетинг 35 год

Правое и левое внешние соединения функционально эквивалентны. Ни один из них не обеспечивает какой-либо функциональности, чем другой, поэтому правое и левое внешнее объединение могут заменять друг друга, если порядок в таблице меняется.

Диаграмма Венна, показывающая правый круг, левый круг и перекрывающуюся часть с заливкой.
Диаграмма Венна, представляющая оператор SQL Full Join между таблицами A и B.

Полное внешнее соединение

Концептуально полное внешнее соединение сочетает в себе эффект применения как левого, так и правого внешних объединений. Если строки в FULL OUTER JOINed таблицах не совпадают, набор результатов будет иметь значения NULL для каждого столбца таблицы, в котором отсутствует соответствующая строка. Для тех строк, которые действительно совпадают, в результирующем наборе будет создана одна строка (содержащая столбцы, заполненные из обеих таблиц).

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

Пример полного внешнего соединения ( OUTERключевое слово необязательно):

SELECT *
FROM employee FULL OUTER JOIN department
  ON employee.DepartmentID = department.DepartmentID;
Employee.LastName Employee.DepartmentID Department.DepartmentName Department.DepartmentID
Смит 34 Канцелярский 34
Джонс 33 Инженерное дело 33
Робинсон 34 Канцелярский 34
Уильямс NULL NULL NULL
Гейзенберг 33 Инженерное дело 33
Рафферти 31 год Продажи 31 год
NULL NULL Маркетинг 35 год

Некоторые системы баз данных не поддерживают полную функциональность внешнего соединения напрямую, но они могут имитировать ее с помощью внутреннего соединения и выбора UNION ALL «строк одной таблицы» из левой и правой таблиц соответственно. Тот же пример может выглядеть следующим образом:

SELECT employee.LastName, employee.DepartmentID,
       department.DepartmentName, department.DepartmentID
FROM employee
INNER JOIN department ON employee.DepartmentID = department.DepartmentID

UNION ALL

SELECT employee.LastName, employee.DepartmentID,
       cast(NULL as varchar(20)), cast(NULL as integer)
FROM employee
WHERE NOT EXISTS (
    SELECT * FROM department
             WHERE employee.DepartmentID = department.DepartmentID)

UNION ALL

SELECT cast(NULL as varchar(20)), cast(NULL as integer),
       department.DepartmentName, department.DepartmentID
FROM department
WHERE NOT EXISTS (
    SELECT * FROM employee
             WHERE employee.DepartmentID = department.DepartmentID)

Другим подходом может быть UNION ALL левого внешнего соединения и правого внешнего соединения MINUS internal join.

Самостоятельное присоединение

Самосоединение - это присоединение таблицы к самой себе.

Пример

Если бы были две отдельные таблицы для сотрудников и запрос, который запрашивал сотрудников в первой таблице, имеющих ту же страну, что и сотрудники во второй таблице, для поиска таблицы ответов можно было бы использовать обычную операцию объединения. Однако вся информация о сотрудниках содержится в одной большой таблице.

Рассмотрим модифицированную Employeeтаблицу, например следующую:

Таблица сотрудников
EmployeeID Фамилия Страна DepartmentID
123 Рафферти Австралия 31 год
124 Джонс Австралия 33
145 Гейзенберг Австралия 33
201 Робинсон Соединенные Штаты 34
305 Смит Германия 34
306 Уильямс Германия NULL

Пример запроса решения может быть следующим:

SELECT F.EmployeeID, F.LastName, S.EmployeeID, S.LastName, F.Country
FROM Employee F INNER JOIN Employee S ON F.Country = S.Country
WHERE F.EmployeeID < S.EmployeeID
ORDER BY F.EmployeeID, S.EmployeeID;

В результате создается следующая таблица.

Таблица сотрудников после самостоятельного присоединения по странам
EmployeeID Фамилия EmployeeID Фамилия Страна
123 Рафферти 124 Джонс Австралия
123 Рафферти 145 Гейзенберг Австралия
124 Джонс 145 Гейзенберг Австралия
305 Смит 306 Уильямс Германия

В этом примере:

  • Fи Sявляются псевдонимами для первой и второй копий таблицы сотрудников.
  • Условие F.Country = S.Countryисключает пары между сотрудниками в разных странах. В примере вопроса требовались только пары сотрудников из одной страны.
  • Условие F.EmployeeID < S.EmployeeIDисключает пары, в которых значение EmployeeIDпервого сотрудника больше или равно значению EmployeeIDвторого сотрудника. Другими словами, эффект этого условия состоит в том, чтобы исключить повторяющиеся пары и самопары. Без него была бы сгенерирована следующая менее полезная таблица (в таблице ниже отображается только часть результата "Германия"):
EmployeeID Фамилия EmployeeID Фамилия Страна
305 Смит 305 Смит Германия
305 Смит 306 Уильямс Германия
306 Уильямс 305 Смит Германия
306 Уильямс 306 Уильямс Германия

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

Альтернативы

Эффект внешнего соединения также может быть получен с помощью UNION ALL между INNER JOIN и SELECT строк в «основной» таблице, которые не удовлетворяют условию соединения. Например,

SELECT employee.LastName, employee.DepartmentID, department.DepartmentName
FROM employee
LEFT OUTER JOIN department ON employee.DepartmentID = department.DepartmentID;

также можно записать как

SELECT employee.LastName, employee.DepartmentID, department.DepartmentName
FROM employee
INNER JOIN department ON employee.DepartmentID = department.DepartmentID

UNION ALL

SELECT employee.LastName, employee.DepartmentID, cast(NULL as varchar(20))
FROM employee
WHERE NOT EXISTS (
    SELECT * FROM department
             WHERE employee.DepartmentID = department.DepartmentID)

Реализация

Большая часть работы в системах баз данных была направлена ​​на эффективную реализацию объединений, потому что реляционные системы обычно требуют объединения, но сталкиваются с трудностями в оптимизации их эффективного выполнения. Проблема возникает из-за того, что внутренние соединения работают как коммутативно, так и ассоциативно . На практике это означает, что пользователь просто предоставляет список таблиц для объединения и используемые условия объединения, а перед системой базы данных стоит задача определить наиболее эффективный способ выполнения операции. Оптимизатор запросов определяет , как выполнить запрос , содержащий соединения. Оптимизатор запросов имеет две основные свободы:

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

Многие алгоритмы соединения по-разному обрабатывают свои входные данные. Можно ссылаться на входы соединения как на «внешний» и «внутренний» операнды соединения, или «левый» и «правый», соответственно. Например, в случае вложенных циклов система базы данных будет сканировать все внутреннее отношение для каждой строки внешнего отношения.

Планы запросов, включающие объединения, можно классифицировать следующим образом:

левый
использование базовой таблицы (а не другого соединения) в качестве внутреннего операнда каждого соединения в плане
глубоко
использование базовой таблицы в качестве внешнего операнда каждого соединения в плане
кустистый
ни влево, ни вправо; оба входа в соединение могут сами быть результатом объединений

Эти имена являются производными от внешнего вида плана запроса, если он изображен в виде дерева , с внешним отношением соединения слева и внутренним отношением справа (как того требует соглашение).

Алгоритмы соединения

Три основных алгоритмы для выполнения операции соединение существует: вложенный цикл , сортировки слияния и хэш - соединение .

Присоединить индексы

Индексы соединения - это индексы базы данных, которые облегчают обработку запросов соединения в хранилищах данных : в настоящее время (2012 г.) они доступны в реализациях Oracle и Teradata .

В реализации Teradata указанные столбцы, агрегатные функции для столбцов или компоненты столбцов даты из одной или нескольких таблиц задаются с использованием синтаксиса, аналогичного определению представления базы данных : до 64 столбцов / выражений столбцов можно указать в одном присоединиться к index. При желании также может быть указан столбец, определяющий первичный ключ составных данных: на параллельном оборудовании значения столбца используются для разделения содержимого индекса по нескольким дискам. Когда исходные таблицы обновляются пользователями в интерактивном режиме, содержимое индекса объединения обновляется автоматически. Любой запрос, предложение WHERE которого определяет любую комбинацию столбцов или выражений столбцов, которые являются точным подмножеством тех, которые определены в индексе соединения (так называемый «покрывающий запрос»), вызовет индекс соединения, а не исходные таблицы и их индексы, для консультации во время выполнения запроса.

Реализация Oracle ограничивается использованием индексов растровых изображений . Растровый присоединиться индекс используется для низкого мощностных столбцов (т.е. столбцы , содержащие меньше , чем 300 различных значений, в соответствии с документацией Oracle): он сочетает в себе с низким мощностные столбцы из нескольких связанных таблиц. Oracle использует пример системы инвентаризации, в которой разные поставщики предоставляют разные детали. В схеме есть три связанных таблицы: две «основные таблицы», «Деталь и поставщик», и «подробная таблица», «Инвентарь». Последняя представляет собой таблицу «многие ко многим», связывающую поставщика с деталью и содержащую наибольшее количество строк. Каждая деталь имеет тип детали, а каждый поставщик находится в США и имеет столбец "Штат". В США не более 60 штатов + территорий и не более 300 типов деталей. Индекс соединения растрового изображения определяется с использованием стандартного соединения трех таблиц для трех таблиц выше и определения столбцов Part_Type и Supplier_State для индекса. Однако он определен в таблице Inventory, даже несмотря на то, что столбцы Part_Type и Supplier_State «заимствованы» у поставщика и детали соответственно.

Что касается Teradata, индекс соединения растрового изображения Oracle используется только для ответа на запрос, когда в предложении WHERE запроса указаны столбцы, ограниченные теми, которые включены в индекс соединения.

Прямое соединение

Некоторые системы баз данных позволяют пользователю заставить систему читать таблицы в соединении в определенном порядке. Это используется, когда оптимизатор соединения выбирает чтение таблиц в неэффективном порядке. Например, в MySQL команда STRAIGHT_JOINсчитывает таблицы точно в том порядке, в котором они указаны в запросе.

Смотрите также

использованная литература

Цитаты

Источники

внешние ссылки