Предложение join в языке структурированных запросов ( SQL ) объединяет столбцы из одной или нескольких таблиц в новую таблицу. Операция соответствует операции join в реляционной алгебре . Неформально, join сшивает две таблицы и помещает в одну строку записи с совпадающими полями: INNER
, LEFT OUTER
, RIGHT OUTER
, FULL OUTER
и CROSS
.
Для объяснения типов соединений в оставшейся части статьи используются следующие таблицы:
Department.DepartmentID
является первичным ключом таблицы Department
, тогда как Employee.DepartmentID
является внешним ключом .
Обратите внимание, что в Employee
, "Williams" еще не был назначен в отдел. Также ни один сотрудник не был назначен в отдел "Marketing".
Ниже приведены операторы SQL для создания приведенных выше таблиц:
СОЗДАТЬ ТАБЛИЦУ отдел ( DepartmentID INT ПЕРВИЧНЫЙ КЛЮЧ НЕ NULL , Название отдела VARCHAR ( 20 ) );СОЗДАТЬ ТАБЛИЦУ сотрудник ( Фамилия VARCHAR ( 20 ), DepartmentID INT ССЫЛКИ отдел ( DepartmentID ) );ВСТАВИТЬ В ОТДЕЛ ЦЕННОСТИ ( 31 , «Продажи» ), ( 33 , «Инженерное дело» ), ( 34 , «Духовный» ), ( 35 , «Маркетинг» ); ВСТАВИТЬ В сотрудника ЦЕННОСТИ ( 'Рафферти' , 31 ), ( 'Джонс' , 33 ), ( 'Гейзенберг' , 33 ), ( 'Робинзон' , 34 ), ( 'Смит' , 34 ), ( 'Вильямс' , NULL );
CROSS JOIN
возвращает декартово произведение строк из таблиц в соединении. Другими словами, он создаст строки, которые объединяют каждую строку из первой таблицы с каждой строкой из второй таблицы. [1]
Пример явного перекрестного соединения:
ВЫБРАТЬ * ИЗ СОТРУДНИКА CROSS JOIN отдел ;
Пример неявного перекрестного соединения:
ВЫБРАТЬ * ИЗ сотрудника , отдела ;
Перекрестное соединение можно заменить внутренним соединением с всегда истинным условием:
ВЫБРАТЬ * ИЗ СОТРУДНИКА ВНУТРЕННЕЕ СОЕДИНЕНИЕ ОТДЕЛ ВКЛ 1 = 1 ;
CROSS JOIN
сам по себе не применяет никаких предикатов для фильтрации строк из объединенной таблицы. Результаты a CROSS JOIN
могут быть отфильтрованы с помощью WHERE
предложения, которое затем может создать эквивалент внутреннего соединения.
В стандарте SQL:2011 перекрестные соединения являются частью необязательного пакета F401 «Расширенная объединенная таблица».
Обычно используется для проверки производительности сервера. [ зачем? ]
Внутреннее соединение ( или join ) требует, чтобы каждая строка в двух соединенных таблицах имела совпадающие значения столбцов, и является широко используемой операцией соединения в приложениях, но не должно считаться лучшим выбором во всех ситуациях. Внутреннее соединение создает новую таблицу результатов путем объединения значений столбцов двух таблиц (A и B) на основе предиката соединения. Запрос сравнивает каждую строку A с каждой строкой B, чтобы найти все пары строк, которые удовлетворяют предикату соединения. Когда предикат соединения удовлетворяется путем сопоставления непустых значений , значения столбцов для каждой совпавшей пары строк A и B объединяются в строку результата.
Результат соединения можно определить как результат первого взятия декартова произведения (или перекрестного соединения) всех строк в таблицах (объединяя каждую строку в таблице A с каждой строкой в таблице B), а затем возвращая все строки, которые удовлетворяют предикату соединения. Фактические реализации SQL обычно используют другие подходы, такие как хэш-соединения или сортировочно-слиятельные соединения , поскольку вычисление декартова произведения происходит медленнее и часто требует непозволительно большого объема памяти для хранения.
SQL определяет два различных синтаксических способа выражения соединений: «явная нотация соединения» и «неявная нотация соединения». «Неявная нотация соединения» больше не считается лучшей практикой [ кем? ] , хотя системы баз данных все еще поддерживают ее.
«Явная нотация соединения» использует ключевое JOIN
слово, которому может предшествовать INNER
ключевое слово, для указания таблицы для соединения, а также ON
ключевое слово для указания предикатов для соединения, как в следующем примере:
SELECT сотрудник.Фамилия , сотрудник.ID отдела , отдел.Название отдела FROM сотрудник INNER JOIN отдел ON сотрудник.ID отдела = отдел.ID отдела ;
«Неявная нотация соединения» просто перечисляет таблицы для соединения в FROM
предложении оператора SELECT
, используя запятые для их разделения. Таким образом, она определяет перекрестное соединение, и WHERE
предложение может применять дополнительные фильтры-предикаты (которые функционируют сопоставимо с предикатами соединения в явной нотации).
Следующий пример эквивалентен предыдущему, но на этот раз с использованием неявной нотации соединения:
SELECT сотрудник.Фамилия , сотрудник.ID отдела , отдел.Название отдела FROM сотрудник , отдел WHERE сотрудник.ID отдела = отдел.ID отдела ;
Запросы, приведенные в примерах выше, объединят таблицы Employee и department, используя столбец DepartmentID обеих таблиц. Если DepartmentID этих таблиц совпадают (т.е. предикат join-predicate выполняется), запрос объединит столбцы LastName , DepartmentID и DepartmentName из двух таблиц в строку результата. Если DepartmentID не совпадает, строка результата не генерируется.
Таким образом, результатом выполнения приведенного выше запроса будет:
Сотрудник "Williams" и отдел "Marketing" не отображаются в результатах выполнения запроса. Ни один из них не имеет соответствующих строк в другой соответствующей таблице: у "Williams" нет связанного отдела, и ни один сотрудник не имеет идентификатора отдела 35 ("Marketing"). В зависимости от желаемых результатов, такое поведение может быть тонкой ошибкой, которую можно избежать, заменив внутреннее соединение внешним соединением.
Программистам следует проявлять особую осторожность при соединении таблиц по столбцам, которые могут содержать значения NULL , поскольку NULL никогда не будет соответствовать никакому другому значению (даже самому NULL), если только условие соединения явно не использует предикат сочетания, который сначала проверяет, что столбцы соединения имеют значение, NOT NULL
прежде чем применять оставшиеся условия предиката. Внутреннее соединение можно безопасно использовать только в базе данных, которая обеспечивает ссылочную целостность или где столбцы соединения гарантированно не будут иметь значение NULL. Многие реляционные базы данных обработки транзакций полагаются на стандарты обновления данных атомарности, согласованности, изоляции, долговечности (ACID) для обеспечения целостности данных, что делает внутренние соединения подходящим выбором. Однако в транзакционных базах данных обычно также есть желательные столбцы соединения, которые могут иметь значение NULL. Многие реляционные базы данных и хранилища данных для отчетов используют пакетные обновления извлечения, преобразования, загрузки (ETL) большого объема, что затрудняет или делает невозможным обеспечение ссылочной целостности, что приводит к потенциально NULL-столбцам соединения, которые автор SQL-запроса не может изменить, и которые приводят к тому, что внутренние соединения пропускают данные без указания на ошибку. Выбор использования внутреннего соединения зависит от структуры базы данных и характеристик данных. Левое внешнее соединение обычно можно заменить внутренним соединением, когда столбцы соединения в одной таблице могут содержать значения NULL.
Любой столбец данных, который может быть пустым (NULL), никогда не должен использоваться в качестве ссылки во внутреннем соединении, если только предполагаемым результатом не является исключение строк со значением NULL. Если столбцы соединения NULL должны быть намеренно удалены из набора результатов , внутреннее соединение может быть быстрее внешнего соединения, поскольку соединение таблиц и фильтрация выполняются за один шаг. И наоборот, внутреннее соединение может привести к катастрофически низкой производительности или даже к сбою сервера при использовании в запросе большого объема в сочетании с функциями базы данных в предложении SQL Where. [2] [3] [4] Функция в предложении SQL Where может привести к тому, что база данных будет игнорировать относительно компактные индексы таблиц. База данных может считывать и выполнять внутреннее соединение выбранных столбцов из обеих таблиц, прежде чем уменьшить количество строк с помощью фильтра, который зависит от вычисленного значения, что приводит к относительно большому объему неэффективной обработки.
Когда набор результатов создается путем объединения нескольких таблиц, включая главные таблицы, используемые для поиска полнотекстовых описаний числовых кодов идентификаторов ( таблица поиска ), значение NULL в любом из внешних ключей может привести к удалению всей строки из набора результатов без указания на ошибку. Сложный SQL-запрос, включающий одно или несколько внутренних соединений и несколько внешних соединений, имеет тот же риск для значений NULL в столбцах ссылок внутреннего соединения.
Приверженность коду SQL, содержащему внутренние соединения, предполагает, что столбцы соединений NULL не будут вводиться в результате будущих изменений, включая обновления поставщиков, изменения дизайна и массовую обработку за пределами правил проверки данных приложения, таких как преобразования данных, миграции, массовый импорт и слияния.
Внутренние соединения можно далее классифицировать как эквисоединения, естественные соединения или перекрестные соединения.
Экви -соединение — это особый тип объединения на основе компаратора, который использует только сравнения равенства в предикате объединения. Использование других операторов сравнения (таких как <
) дисквалифицирует объединение как экви-соединение. Запрос, показанный выше, уже предоставил пример экви-соединения:
SELECT * FROM employee JOIN department ON employee.DepartmentID = department.DepartmentID ;
Мы можем записать эквисоединение следующим образом:
SELECT * FROM сотрудник , отдел WHERE сотрудник.IDОтдела = отдел.IDОтдела ;
Если столбцы в эквиобъединении имеют одинаковые имена, SQL-92 предоставляет необязательную сокращенную запись для выражения эквиобъединений с помощью конструкции USING
: [5]
SELECT * FROM employee INNER JOIN department USING ( DepartmentID );
Однако эта USING
конструкция — больше, чем просто синтаксический сахар , поскольку результирующий набор отличается от результирующего набора версии с явным предикатом. В частности, любые столбцы, упомянутые в списке, USING
будут появляться только один раз с неквалифицированным именем, а не один раз для каждой таблицы в соединении. В приведенном выше случае будет один DepartmentID
столбец и ни одного employee.DepartmentID
или department.DepartmentID
.
Данное USING
предложение не поддерживается MS SQL Server и Sybase.
Естественное соединение является частным случаем эквисоединения. Естественное соединение (⋈) является бинарным оператором , который записывается как ( R ⋈ S ), где R и S являются отношениями . [6] Результатом естественного соединения является набор всех комбинаций кортежей в R и S , которые равны по своим общим именам атрибутов. Для примера рассмотрим таблицы Employee и Dept и их естественное соединение:
Это также можно использовать для определения состава отношений . Например, состав Employee и Dept является их объединением, как показано выше, спроецированным на все, кроме общего атрибута DeptName . В теории категорий объединение является именно произведением волокон .
Естественное соединение, возможно, является одним из самых важных операторов, поскольку оно является реляционным аналогом логического И. Обратите внимание, что если одна и та же переменная появляется в каждом из двух предикатов, которые связаны с помощью И, то эта переменная обозначает одно и то же, и оба появления всегда должны быть заменены одним и тем же значением. В частности, естественное соединение позволяет объединять отношения, которые связаны внешним ключом . Например, в приведенном выше примере внешний ключ, вероятно, содержится от Employee . DeptName до Dept. DeptName , а затем естественное соединение Employee и Dept объединяет всех сотрудников с их отделами. Это работает, потому что внешний ключ содержится между атрибутами с одинаковыми именами. Если это не так, например, во внешнем ключе от Dept. manager до Employee . Name , то эти столбцы необходимо переименовать до того , как будет выполнено естественное соединение. Такое соединение иногда также называют экви-соединением .
Более формально семантика естественного соединения определяется следующим образом:
где Fun — предикат , который истинен для отношения r тогда и только тогда, когда r — функция. Обычно требуется, чтобы R и S имели хотя бы один общий атрибут, но если это ограничение опущено, а R и S не имеют общих атрибутов, то естественное соединение становится в точности декартовым произведением.
Естественное соединение можно смоделировать с помощью примитивов Кодда следующим образом. Пусть c 1 , ..., c m будут именами атрибутов, общими для R и S , r 1 , ..., r n будут именами атрибутов, уникальными для R , и пусть s 1 , ..., s k будут атрибутами, уникальными для S . Кроме того, предположим, что имена атрибутов x 1 , ..., x m отсутствуют ни в R , ни в S . На первом этапе общие имена атрибутов в S теперь можно переименовать:
Затем мы берем декартово произведение и выбираем кортежи, которые необходимо объединить:
Естественное соединение — это тип эквисоединения, где предикат соединения возникает неявно путем сравнения всех столбцов в обеих таблицах, имеющих одинаковые имена столбцов в объединенных таблицах. Результирующая объединенная таблица содержит только один столбец для каждой пары одинаково названных столбцов. В случае, если столбцы с одинаковыми именами не найдены, результатом является перекрестное соединение .
Большинство экспертов сходятся во мнении, что ЕСТЕСТВЕННЫЕ СОЕДИНЕНИЯ опасны, и поэтому настоятельно не рекомендуют их использовать. [7] Опасность возникает из-за непреднамеренного добавления нового столбца, названного так же, как другой столбец в другой таблице. Существующее естественное соединение может затем «естественно» использовать новый столбец для сравнений, выполняя сравнения/соответствия с использованием других критериев (из других столбцов), чем раньше. Таким образом, существующий запрос может выдать другие результаты, даже если данные в таблицах не были изменены, а только дополнены. Использование имен столбцов для автоматического определения связей таблиц не является вариантом в больших базах данных с сотнями или тысячами таблиц, где это наложило бы нереалистичное ограничение на соглашения об именовании. Реальные базы данных обычно разрабатываются с данными внешнего ключа , которые не заполняются последовательно (допустимы значения NULL) из-за бизнес-правил и контекста. Обычной практикой является изменение имен столбцов схожих данных в разных таблицах, и это отсутствие жесткой согласованности переводит естественные соединения в разряд теоретической концепции для обсуждения.
Приведенный выше пример запроса для внутренних соединений можно выразить как естественное соединение следующим образом:
ВЫБРАТЬ * ИЗ сотрудника ЕСТЕСТВЕННЫЙ ПРИСОЕДИНИТЬСЯ отдел ;
Как и в случае явного USING
предложения, в объединенной таблице встречается только один столбец DepartmentID без квалификатора:
PostgreSQL, MySQL и Oracle поддерживают естественные соединения; Microsoft T-SQL и IBM DB2 — нет. Столбцы, используемые в соединении, неявные, поэтому код соединения не показывает, какие столбцы ожидаются, а изменение имен столбцов может изменить результаты. В стандарте SQL:2011 естественные соединения являются частью необязательного пакета F401, "Extended join table",
Во многих средах баз данных имена столбцов контролируются внешним поставщиком, а не разработчиком запроса. Естественное соединение предполагает стабильность и согласованность имен столбцов, которые могут меняться во время обновлений версий, предписанных поставщиком.
Объединенная таблица сохраняет каждую строку — даже если не существует другой соответствующей строки. Внешние соединения далее подразделяются на левые внешние соединения, правые внешние соединения и полные внешние соединения, в зависимости от того, какие строки таблицы сохраняются: левые, правые или обе (в этом случае левые и правые относятся к двум сторонам ключевого JOIN
слова). Как и внутренние соединения, можно далее подразделить все типы внешних соединений на экви-соединения, естественные соединения ( θ -соединение ) и т. д. [8]ON <predicate>
В стандартном SQL не существует неявной нотации для внешних соединений.
Результат левого внешнего соединения (или просто левого соединения ) для таблиц A и B всегда содержит все строки «левой» таблицы (A), даже если условие соединения не находит ни одной соответствующей строки в «правой» таблице (B). Это означает, что если ON
предложение соответствует 0 (нулю) строк в B (для заданной строки в A), соединение все равно вернет строку в результате (для этой строки) — но с NULL в каждом столбце из B. Левое внешнее соединение возвращает все значения из внутреннего соединения плюс все значения в левой таблице, которые не соответствуют правой таблице, включая строки со значениями NULL (пустыми) в столбце ссылки.
Например, это позволяет нам найти отдел, в котором работает сотрудник, но при этом показывать сотрудников, которые не были назначены в отдел (в отличие от примера внутреннего соединения выше, где не назначенные сотрудники были исключены из результата).
Пример левого внешнего соединения ( OUTER
ключевое слово необязательно) с дополнительной строкой результата (по сравнению с внутренним соединением), выделенной курсивом:
SELECT * FROM employee LEFT OUTER JOIN department ON employee . DepartmentID = department . DepartmentID ;
Oracle поддерживает устаревший синтаксис [9] :
ВЫБРАТЬ * ИЗ сотрудник , отдел ГДЕ сотрудник.IDОтдела = отдел.IDОтдела ( + )
Sybase поддерживает следующий синтаксис ( Microsoft SQL Server не рекомендует использовать этот синтаксис с версии 2000):
SELECT * FROM сотрудник , отдел WHERE сотрудник . DepartmentID *= отдел . DepartmentID
IBM Informix поддерживает синтаксис:
ВЫБРАТЬ * ИЗ сотрудника , ВНЕШНИЙ отдел ГДЕ сотрудник.IDОтдела = отдел.IDОтдела
Правое внешнее соединение (или правое соединение ) очень похоже на левое внешнее соединение, за исключением того, что обработка таблиц обратная. Каждая строка из "правой" таблицы (B) появится в объединенной таблице по крайней мере один раз. Если не существует соответствующей строки из "левой" таблицы (A), в столбцах из A для тех строк, которые не имеют соответствия в B, появится NULL.
Правое внешнее соединение возвращает все значения из правой таблицы и соответствующие значения из левой таблицы (NULL в случае отсутствия соответствующего предиката соединения). Например, это позволяет нам найти каждого сотрудника и его отдел, но при этом показывать отделы, в которых нет сотрудников.
Ниже приведен пример правого внешнего соединения ( OUTER
ключевое слово необязательно), при этом дополнительная строка результата выделена курсивом:
SELECT * FROM employee RIGHT OUTER JOIN department ON employee . DepartmentID = department . DepartmentID ;
Правые и левые внешние соединения функционально эквивалентны. Ни одно из них не предоставляет никакой функциональности, которой нет у другого, поэтому правые и левые внешние соединения могут заменять друг друга, если порядок таблиц изменен.
Концептуально полное внешнее соединение объединяет эффект применения как левого, так и правого внешнего соединения. Если строки в таблицах с полным внешним соединением не совпадают, в результирующем наборе будут значения NULL для каждого столбца таблицы, в котором отсутствует соответствующая строка. Для тех строк, которые совпадают, в результирующем наборе будет создана одна строка (содержащая столбцы, заполненные из обеих таблиц).
Например, это позволяет нам видеть каждого сотрудника, работающего в отделе, и каждый отдел, в котором есть сотрудник, но также видеть каждого сотрудника, не работающего в отделе, и каждый отдел, в котором нет сотрудника.
Пример полного внешнего соединения ( OUTER
ключевое слово необязательно):
SELECT * FROM employee FULL OUTER JOIN department ON employee . DepartmentID = department . DepartmentID ;
Некоторые системы баз данных не поддерживают полностью функциональность внешнего соединения напрямую, но они могут эмулировать его с помощью внутреннего соединения и UNION ALL выбирает "отдельные строки таблицы" из левой и правой таблиц соответственно. Тот же пример может выглядеть следующим образом:
SELECT employee.LastName , employee.DepartmentID , department.DepartmentName , department.DepartmentID FROM employee INNER JOIN department ON employee.DepartmentID = department.DepartmentID СОЮЗ ВСЕХ 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 ) СОЮЗ ВСЕХ SELECT приведение ( NULL как varchar ( 20 )), приведение ( NULL как целое число ), отдел . НазваниеОтдела , отдел . КодОтдела FROM отдел, ГДЕ НЕ СУЩЕСТВУЕТ ( SELECT * FROM сотрудник , ГДЕ сотрудник . КодОтдела = отдел . КодОтдела )
Другой подход может заключаться в объединении всех левых внешних соединений и правых внешних соединений за вычетом внутренних соединений.
Самосоединение — это присоединение таблицы к самой себе. [10]
Если бы было две отдельные таблицы для сотрудников и запрос, который запрашивал бы сотрудников в первой таблице, имеющих ту же страну, что и сотрудники во второй таблице, можно было бы использовать обычную операцию соединения, чтобы найти таблицу ответов. Однако вся информация о сотрудниках содержится в одной большой таблице. [11]
Рассмотрим модифицированную Employee
таблицу, например следующую:
Пример запроса на решение может быть следующим:
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 ;
В результате получается следующая таблица.
Для этого примера:
F
и S
являются псевдонимами для первой и второй копий таблицы сотрудников.F.Country = S.Country
исключает пары между сотрудниками из разных стран. В примере вопроса требовались только пары сотрудников из одной страны.F.EmployeeID < S.EmployeeID
исключает пары, где EmployeeID
первого сотрудника больше или равно EmployeeID
второго сотрудника. Другими словами, эффект этого условия заключается в исключении дублирующих пар и пар с самим собой. Без него была бы сгенерирована следующая менее полезная таблица (таблица ниже отображает только часть результата «Германия»):Для решения исходного вопроса необходима только одна из двух средних пар, а самая верхняя и самая нижняя в этом примере вообще не представляют интереса.
Эффект внешнего соединения также может быть получен с помощью 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 СОЮЗ ВСЕХ SELECT employee.LastName , employee.DepartmentID , cast ( NULL as varchar ( 20 ) ) FROM employee WHERE NOT EXISTS ( SELECT * FROM department WHERE employee.DepartmentID = department.DepartmentID )
Большая часть работы в системах баз данных была направлена на эффективную реализацию объединений, поскольку реляционные системы обычно требуют объединений, но сталкиваются с трудностями в оптимизации их эффективного выполнения. Проблема возникает из-за того, что внутренние объединения работают как коммутативно , так и ассоциативно . На практике это означает, что пользователь просто предоставляет список таблиц для объединения и условия объединения для использования, а система базы данных должна определить наиболее эффективный способ выполнения операции. Выбор становится более сложным по мере увеличения количества таблиц, вовлеченных в запрос, при этом каждая таблица имеет различные характеристики по количеству записей, средней длине записи (с учетом полей NULL) и доступным индексам. Фильтры Where Clause также могут существенно влиять на объем и стоимость запроса.
Оптимизатор запросов определяет, как выполнить запрос, содержащий объединения. Оптимизатор запросов имеет две основные свободы:
Многие алгоритмы соединения по-разному обрабатывают свои входные данные. Входные данные для соединения можно называть «внешними» и «внутренними» операндами соединения, или «левыми» и «правыми» соответственно. Например, в случае вложенных циклов система базы данных будет сканировать все внутреннее отношение для каждой строки внешнего отношения.
Можно классифицировать планы запросов, включающие соединения, следующим образом: [12]
Эти названия происходят от внешнего вида плана запроса , если его изобразить в виде дерева , с внешним отношением соединения слева и внутренним отношением справа (как того требует соглашение).
Существуют три основных алгоритма для выполнения операции бинарного соединения: соединение вложенных циклов , соединение сортировкой-слиянием и хэш-соединение . Оптимальные алгоритмы соединения в худшем случае асимптотически быстрее алгоритмов бинарного соединения для соединений между более чем двумя отношениями в худшем случае .
Индексы соединений — это индексы баз данных , которые облегчают обработку запросов на соединение в хранилищах данных : в настоящее время (2012) они доступны в реализациях Oracle [14] и Teradata [15] .
В реализации Teradata указанные столбцы, агрегатные функции для столбцов или компоненты столбцов даты из одной или нескольких таблиц указываются с использованием синтаксиса, похожего на определение представления базы данных : в одном индексе соединения можно указать до 64 столбцов/выражений столбцов. При желании можно также указать столбец, определяющий первичный ключ составных данных: на параллельном оборудовании значения столбцов используются для разделения содержимого индекса по нескольким дискам. Когда исходные таблицы обновляются пользователями в интерактивном режиме, содержимое индекса соединения автоматически обновляется. Любой запрос, предложение WHERE которого указывает любую комбинацию столбцов или выражений столбцов, которые являются точным подмножеством определенных в индексе соединения (так называемый «покрывающий запрос»), приведет к тому, что во время выполнения запроса будет обращаться к индексу соединения, а не к исходным таблицам и их индексам.
Реализация Oracle ограничивается использованием индексов bitmap . Индекс bitmap join используется для столбцов с низкой кардинальностью (т. е. столбцов, содержащих менее 300 различных значений, согласно документации Oracle): он объединяет столбцы с низкой кардинальностью из нескольких связанных таблиц. Пример, который использует Oracle, — это система инвентаризации, где разные поставщики предоставляют разные детали. Схема имеет три связанных таблицы: две «главные таблицы», Part и Supplier, и «подробную таблицу», Inventory. Последняя представляет собой таблицу «многие ко многим», связывающую Supplier с Part, и содержит наибольшее количество строк. Каждая деталь имеет тип Part, и каждый поставщик находится в США и имеет столбец State. В США не более 60 штатов и территорий и не более 300 типов Part. Индекс bitmap join определяется с помощью стандартного трехтабличного соединения для трех таблиц выше и указания столбцов Part_Type и Supplier_State для индекса. Однако он определен в таблице «Инвентарь», хотя столбцы «Тип детали» и «Состояние поставщика» «заимствованы» из таблиц «Поставщик» и «Деталь» соответственно.
Что касается Teradata, индекс соединения по битовой карте Oracle используется для ответа на запрос только в том случае, если в предложении WHERE запроса указаны столбцы, ограниченные теми, которые включены в индекс соединения.
Некоторые системы баз данных позволяют пользователю заставить систему читать таблицы в соединении в определенном порядке. Это используется, когда оптимизатор соединения выбирает чтение таблиц в неэффективном порядке. Например, в MySQL команда STRAIGHT_JOIN
читает таблицы точно в том порядке, который указан в запросе. [16]