@avi левое и правое объединения похожи, если вас не беспокоит, на какой основной таблице основано соединение.
Anup
2
@philipxy: Это странное определение (даже если вы правы). Но я бы предпочел пойти другим путем и начать с перекрестного соединения, а затем «построить» внутреннее соединение поверх него. В конце концов, простая концепция перекрестного соединения делает недействительными эти неформальные и неточные визуализации диаграмм Венна ...
Лукас Эдер,
1
Эти рисунки, кажется, подразумевают, что объединение такое же, как полное внешнее соединение, а пересечение такое же, как и внутреннее соединение, что, насколько я знаю, не является правильным.
mightyWOZ
1
@DevDave, потому что вопреки распространенному мнению - картина не стоит тысячи слов. Смотрите следующий ответ.
Гяньков
248
Что такое SQL JOIN?
SQL JOIN это метод для извлечения данных из двух или более таблиц базы данных.
В этом виде JOINмы получаем все записи, которые соответствуют условию в обеих таблицах, а записи в обеих таблицах, которые не совпадают, не сообщаются.
Другими словами, INNER JOINоснован на единственном факте, что: ТОЛЬКО соответствующие записи в ОБА таблицы должны быть перечислены.
Обратите внимание , что JOINбез каких - либо других JOINключевых слов (например INNER, OUTER, LEFTи т.д.) является INNER JOIN. Другими словами, JOINявляется синтаксическим сахаром для INNER JOIN(см .: Различие между JOIN и INNER JOIN ).
2. НАРУЖНОЕ СОЕДИНЕНИЕ:
OUTER JOIN извлекает
Либо совпадающие строки из одной таблицы и всех строк в другой таблице Или все строки во всех таблицах (не имеет значения, есть ли совпадение).
Существует три вида внешнего соединения:
2.1 ЛЕВОЕ НАРУЖНОЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ
Это соединение возвращает все строки из левой таблицы вместе с соответствующими строками из правой таблицы. Если в правой таблице нет соответствующих столбцов, он возвращает NULLзначения.
2.2 ПРАВИЛЬНОЕ ВСТУПЛЕНИЕ
Это JOINвозвращает все строки из правой таблицы вместе с совпадающими строками из левой таблицы. Если в левой таблице нет соответствующих столбцов, она возвращает NULLзначения.
2.3 ПОЛНОЕ НАРУЖНОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ
Это JOINсочетает в себе LEFT OUTER JOINи RIGHT OUTER JOIN. Он возвращает строки из любой таблицы, когда выполняются условия, и возвращает NULLзначение, если совпадения нет.
Другими словами, OUTER JOINосновано на том факте, что: ДОЛЖНЫ быть перечислены ТОЛЬКО совпадающие записи в ОДНОЙ из таблиц (ВПРАВО или ВЛЕВО) или ОБА из таблиц (ПОЛНАЯ).
Note that `OUTERJOIN`is a loosened form of`INNERJOIN`.
3. ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ:
Он основан на двух условиях:
JOINпроизводится по всем столбцам с тем же именем для равенства.
Удаляет дубликаты столбцов из результата.
Похоже, что это скорее теоретический характер, и в результате (вероятно) большинство СУБД даже не заботятся об этом.
4. CROSS JOIN:
Это декартово произведение двух задействованных таблиц. Результат CROSS JOINне будет иметь смысла в большинстве ситуаций. Более того, нам это вообще не понадобится (или, если быть точным, нужно меньше всего).
5. САМ СОЕДИНЯЙТЕСЬ:
Это не другая форма JOIN, скорее это JOIN( INNER, OUTERи т.д.) из таблицы к себе.
СОЕДИНЕНИЯ на основе операторов
В зависимости от оператора, используемого для JOINпредложения, может быть два типа JOINs. Они есть
Equi JOIN
Тета ПРИСОЕДИНЯЙТЕСЬ
1. Equi JOIN:
Для любого JOINтипа ( INNER, OUTERи т. Д.), Если мы используем ТОЛЬКО оператор равенства (=), то мы говорим, что это JOINявляется EQUI JOIN.
2. Тета ПРИСОЕДИНЯЙТЕСЬ:
Это то же самое, что EQUI JOINи другие операторы, такие как>, <,> = и т. Д.
Многие считают , как EQUI JOINи Theta JOINаналогичны INNER, и OUTER
т.д. JOINs. Но я твердо верю, что это ошибка и делает идеи расплывчатыми. Потому что INNER JOINи OUTER JOINт. Д. Все связаны с таблицами и их данными, тогда как EQUI JOINи THETA JOINсвязаны только с операторами, которые мы используем в первом.
Опять же, есть много людей, которые считают NATURAL JOINсвоего рода «своеобразным» EQUI JOIN. На самом деле, это правда, из-за первого условия, которое я упомянул NATURAL JOIN. Тем не менее, мы не должны ограничивать это просто NATURAL JOINs. INNER JOINs, OUTER JOINs и т EQUI JOIN. д. тоже могут быть .
Относительно новое LATERAL JOIN .. ВЫБЕРИТЕ * ОТ r1, LATERAL fx (r1)
Павел Stehule
13
Хотя это кажется разумным, я не думаю, что ответы «что такое SQL-соединение» каким-либо образом передают полезную информацию. Ответ в целом - справка, написанная для людей, которые уже понимают объединения, а не для людей, которые задают эти вопросы. Он также опускает ссылки, как для поддержки своих утверждений (как уместно, если дает авторский ответ), так и для предоставления дополнительных объяснений через внешние ресурсы. Если вы пытаетесь написать авторитетный ответ, чтобы связать новых пользователей SQL, возможно, стоит немного заполнить пробелы, особенно часть «что такое соединение».
Крейг Рингер,
Можете ли вы привести несколько примеров?
Ави
67
Определение:
СОЕДИНЕНИЯ - это способ запроса данных, которые объединяются из нескольких таблиц одновременно.
Типы СОЕДИНЕНИЙ:
К СУБД относятся 5 типов соединений:
Equi-Join: объединяет общие записи из двух таблиц на основе условия равенства. Технически, соединение выполняется с использованием оператора равенства (=) для сравнения значений первичного ключа одной таблицы и значений внешнего ключа другой таблицы, поэтому набор результатов включает в себя общие (совпавшие) записи из обеих таблиц. Для реализации см. INNER-JOIN.
Natural-Join: это расширенная версия Equi-Join, в которой операция SELECT пропускает повторяющийся столбец. Для реализации см. INNER-JOIN
Non-Equi-Join: это обратное Equi-Join, где используется условие соединения, отличное от оператора равенства (=), например,! =, <=,> =,>, <Или BETWEEN и т. Д. Для реализации см. INNER-JOIN.
Self-Join: настраиваемое поведение объединения, когда таблица объединяется с самим собой; Как правило, это необходимо для запроса к самоссылающимся таблицам (или сущности унарных отношений). Для реализации см. ВНУТРЕННИЕ СОЕДИНЕНИЯ.
Декартово произведение: оно объединяет все записи обеих таблиц без каких-либо условий. Технически он возвращает набор результатов запроса без WHERE-предложения.
В соответствии с требованиями и усовершенствованиями SQL существует 3 типа объединений, и все объединения RDBMS могут быть достигнуты с помощью этих типов объединений.
INNER-JOIN: объединяет (или объединяет) совпадающие строки из двух таблиц. Сопоставление выполняется на основе общих столбцов таблиц и их операции сравнения. Если условие на основе равенства, то: EQUI-JOIN выполняется, в противном случае не-EQUI-Join.
OUTER-JOIN: объединяет (или объединяет) совпавшие строки из двух таблиц и несопоставленные строки со значениями NULL. Однако можно настроить выбор несопоставленных строк, например, выбрать несопоставленную строку из первой или второй таблицы по подтипам: LEFT OUTER JOIN и RIGHT OUTER JOIN.
2.1. LEFT Outer JOIN (он же LEFT-JOIN): возвращает совпадающие строки из двух таблиц и не совпадает только с таблицей LEFT (т. Е. С первой таблицей).
2.2. RIGHT Outer JOIN (он же RIGHT-JOIN): возвращает совпадающие строки из двух таблиц и не совпадает только с правой таблицей.
2,3. FULL OUTER JOIN (он же OUTER JOIN): возвращает совпадения и несоответствия из обеих таблиц.
CROSS-JOIN: это объединение не объединяет / объединяет, а выполняет декартово произведение.
Примечание: Self-JOIN может быть достигнуто с помощью INNER-JOIN, OUTER-JOIN и CROSS-JOIN в зависимости от требований, но таблица должна соединяться сама с собой.
Ярлыки «Таблица 1» и «Таблица 2» и нижние метки неуместны, они взяты из иллюстраций intersect/ except/ union; здесь кружки - это строки, возвращаемые символом left& rightjoin, как говорят пронумерованные метки. Картинка AXB - это чепуха. cross join= inner join on 1=1& является частным случаем первой диаграммы.
Филипп
Стоит отметить, что SQL-92 определяет UNION JOIN. Теперь устарел в SQL: 2003.
The Impaler
40
Интересно, что большинство других ответов страдают от этих двух проблем:
Они сосредоточены только на основных формах объединения
Прежде всего: СОЕДИНЕНИЯ - это декартовы произведения
Вот почему диаграммы Венна объясняют их так неточно, потому что JOIN создает декартово произведение между двумя объединенными таблицами. Википедия это прекрасно иллюстрирует:
SQL синтаксис для декартовых продуктов CROSS JOIN. Например:
SELECT*-- This just generates all the days in January 2017FROM generate_series('2017-01-01'::TIMESTAMP,'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day')AS days(day)-- Here, we're combining all days with all departmentsCROSSJOIN departments
Который объединяет все строки из одной таблицы со всеми строками из другой таблицы:
Источник:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
Результат:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
Если мы просто напишем список таблиц через запятую, мы получим то же самое:
-- CROSS JOINing two tables:SELECT*FROM table1, table2
ВНУТРЕННИЙ РЕЙТИНГ (Theta-JOIN)
An INNER JOIN- это просто фильтр, CROSS JOINгде предикат фильтра вызывается Thetaв реляционной алгебре.
Например:
SELECT*-- Same as beforeFROM generate_series('2017-01-01'::TIMESTAMP,'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day')AS days(day)-- Now, exclude all days/departments combinations for-- days before the department was createdJOIN departments AS d ON day >= d.created_at
Обратите внимание, что ключевое слово INNERявляется необязательным (кроме MS Access).
Специальный вид Theta-JOIN - это equi JOIN, который мы используем чаще всего. Предикат объединяет первичный ключ одной таблицы с внешним ключом другой таблицы. Если мы используем базу данных Sakila для иллюстрации, мы можем написать:
SELECT*FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
Это объединяет всех актеров с их фильмами.
Или также в некоторых базах данных:
SELECT*FROM actor
JOIN film_actor USING(actor_id)JOIN film USING(film_id)
USING()Синтаксис позволяет указать столбец , который должен присутствовать на каждой стороне JOIN таблицы операции и создает предикат равенства этих двух столбцов.
ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ
Другие ответы перечислили этот «тип JOIN» отдельно, но это не имеет смысла. Это просто синтаксическая форма сахара для equi JOIN, которая является частным случаем Theta-JOIN или INNER JOIN. НАТУРАЛЬНОЕ СОЕДИНЕНИЕ просто собирает все столбцы, которые являются общими для обеих объединяемых таблиц, и объединяет USING()эти столбцы. Что вряд ли пригодится из-за случайных совпадений (например, LAST_UPDATEстолбцы в базе данных Sakila ).
Вот синтаксис:
SELECT*FROM actor
NATURALJOIN film_actor
NATURALJOIN film
НАРУЖНОЕ СОЕДИНЕНИЕ
Теперь OUTER JOINнемного отличается от того, INNER JOINкак создает UNIONнесколько декартовых произведений. Мы можем написать:
-- Convenient syntax:SELECT*FROM a LEFTJOIN b ON<predicate>-- Cumbersome, equivalent syntax:SELECT a.*, b.*FROM a JOIN b ON<predicate>UNIONALLSELECT a.*,NULL,NULL,...,NULLFROM a
WHERENOTEXISTS(SELECT*FROM b WHERE<predicate>)
Никто не хочет писать последнее, поэтому мы пишем OUTER JOIN(что обычно лучше оптимизировать с помощью баз данных).
Мол INNER, ключевое слово OUTERздесь необязательно.
OUTER JOIN поставляется в трех вариантах:
LEFT [ OUTER ] JOIN: Левая таблица JOINвыражения добавляется в объединение, как показано выше.
RIGHT [ OUTER ] JOIN: Правая таблица JOINвыражения добавляется в объединение, как показано выше.
FULL [ OUTER ] JOIN: Обе таблицы JOINвыражения добавляются в объединение, как показано выше.
В Oracle и SQL Server существует несколько устаревших синтаксисов, которые поддерживались OUTER JOINеще до того, как стандарт SQL имел синтаксис для этого:
-- OracleSELECT*FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)AND fa.film_id = f.film_id(+)-- SQL ServerSELECT*FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
Сказав это, не используйте этот синтаксис. Я просто перечислю это здесь, чтобы вы могли распознать его по старым постам в блоге / устаревшему коду.
Разделенный OUTER JOIN
Мало кто знает это, но стандарт SQL определяет секционирование OUTER JOIN(и Oracle реализует это). Вы можете написать такие вещи:
WITH-- Using CONNECT BY to generate all dates in January
days(day)AS(SELECT DATE '2017-01-01'+ LEVEL -1FROM dual
CONNECTBY LEVEL <=31),-- Our departments
departments(department, created_at)AS(SELECT'Dept 1', DATE '2017-01-10'FROM dual UNIONALLSELECT'Dept 2', DATE '2017-01-11'FROM dual UNIONALLSELECT'Dept 3', DATE '2017-01-12'FROM dual UNIONALLSELECT'Dept 4', DATE '2017-04-01'FROM dual UNIONALLSELECT'Dept 5', DATE '2017-04-02'FROM dual
)SELECT*FROM days
LEFTJOIN departments
PARTITIONBY(department)-- This is where the magic happensON day >= created_at
Части результата:
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
Дело здесь в том, что все строки с разделенной стороны объединения получат результат независимо от того, JOINсовпадает ли что- нибудь на «другой стороне соединения». Короче говоря: для заполнения редких данных в отчетах. Очень полезно!
SELECT*FROM actor a
WHEREEXISTS(SELECT*FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
WHERE a.actor_id = fa.actor_idПредикат действует как пол Предиката. Если вы не верите этому, проверьте планы выполнения, например, в Oracle. Вы увидите, что база данных выполняет операцию SEMI JOIN, а не EXISTS()предикат.
SELECT*FROM actor a
WHERENOTEXISTS(SELECT*FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Некоторые люди (особенно люди из MySQL) также пишут ANTI JOIN так:
SELECT*FROM actor a
LEFTJOIN film_actor fa
USING(actor_id)WHERE film_id ISNULL
Я думаю, что историческая причина - производительность.
Боковое соединение
О, Боже, это слишком круто. Я единственный, кто упомянул это? Вот крутой запрос:
SELECT a.first_name, a.last_name, f.*FROM actor AS a
LEFTOUTERJOIN LATERAL (SELECT f.title, SUM(amount)AS revenue
FROM film AS f
JOIN film_actor AS fa USING(film_id)JOIN inventory AS i USING(film_id)JOIN rental AS r USING(inventory_id)JOIN payment AS p USING(rental_id)WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!GROUPBY f.film_id
ORDERBY revenue DESC
LIMIT 5)AS f
ON true
Он найдет ТОП-5 доходных фильмов на одного актера. Каждый раз, когда вам нужен запрос TOP-N-за-то, LATERAL JOINбудет вашим другом. Если вы человек SQL Server, то вы знаете этот JOINтип под именемAPPLY
SELECT a.first_name, a.last_name, f.*FROM actor AS a
OUTERAPPLY(SELECT f.title, SUM(amount)AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!GROUPBY f.film_id
ORDERBY revenue DESC
LIMIT 5)AS f
Хорошо, возможно, это обман, потому что выражение LATERAL JOINили APPLY- это действительно «коррелированный подзапрос», который создает несколько строк. Но если мы допустим «коррелированные подзапросы», мы также можем говорить о ...
MULTISET
Это реально реализовано только в Oracle и Informix (насколько мне известно), но его можно эмулировать в PostgreSQL с использованием массивов и / или XML и в SQL Server с использованием XML.
MULTISETсоздает коррелированный подзапрос и вкладывает результирующий набор строк во внешний запрос. Приведенный ниже запрос выбирает всех актеров и для каждого актера собирает свои фильмы во вложенную коллекцию:
SELECT a.*, MULTISET (SELECT f.*FROM film AS f
JOIN film_actor AS fa USING(film_id)WHERE a.actor_id = fa.actor_id
)AS films
FROM actor
Как вы уже видели, есть несколько типов JOIN , чем просто «скучно» INNER, OUTERи CROSS JOINчто, как правило , упоминаются. Подробнее в моей статье . И, пожалуйста, прекратите использовать диаграммы Венна, чтобы проиллюстрировать их.
Equijoin - это особый случай тэта-соединения, где тэта - это равенство. Тета-соединение аналогично частному случаю внутреннего соединения, где on - это тэта-сравнение столбца каждого из них. Через несколько десятилетий после того, как Кодд определил их, некоторые учебники неправильно определили тэта-соединение как обобщение, которое является аналогом внутреннего соединения.
Philipxy
@philipxy: Что-то конкретное, что я должен изменить в своем ответе? Вы могли бы предложить редактировать ...
Лукас Эдер
10
Я создал иллюстрацию, которая объясняет лучше, чем слова, на мой взгляд:
@Niraj Круги A & B не содержат рядов A & B. Они слепо скопированы из других источников без кредита. Перекрестное объединение включено во внутреннее объединение, это внутреннее объединение на 1 = 1. Как эти части изображения "идеальны"?
Филипп
@philipxy Извините, но меня не беспокоит, скопировано ли оно из другого места. и я не уверен, что не правильно на картинке выше. для меня это нормально. Перекрестное соединение здесь не описано. Это не входит во внутреннее объединение ..
Niraj
-3
Я собираюсь нажать мою любимую мозоль: ключевое слово USING.
Если обе таблицы на обеих сторонах JOIN имеют правильные имена своих внешних ключей (т. Е. Одно и то же имя, а не просто «id»), то это можно использовать:
Что такое
SQL JOIN
?SQL JOIN
это метод для извлечения данных из двух или более таблиц базы данных.Каковы разные
SQL JOIN
с?Всего пять
JOIN
с. Они есть :1. Присоединиться или присоединиться
В этом виде
JOIN
мы получаем все записи, которые соответствуют условию в обеих таблицах, а записи в обеих таблицах, которые не совпадают, не сообщаются.Другими словами,
INNER JOIN
основан на единственном факте, что: ТОЛЬКО соответствующие записи в ОБА таблицы должны быть перечислены.Обратите внимание , что
JOIN
без каких - либо другихJOIN
ключевых слов (напримерINNER
,OUTER
,LEFT
и т.д.) являетсяINNER JOIN
. Другими словами,JOIN
является синтаксическим сахаром дляINNER JOIN
(см .: Различие между JOIN и INNER JOIN ).2. НАРУЖНОЕ СОЕДИНЕНИЕ:
OUTER JOIN
извлекаетЛибо совпадающие строки из одной таблицы и всех строк в другой таблице Или все строки во всех таблицах (не имеет значения, есть ли совпадение).
Существует три вида внешнего соединения:
2.1 ЛЕВОЕ НАРУЖНОЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ
Это соединение возвращает все строки из левой таблицы вместе с соответствующими строками из правой таблицы. Если в правой таблице нет соответствующих столбцов, он возвращает
NULL
значения.2.2 ПРАВИЛЬНОЕ ВСТУПЛЕНИЕ
Это
JOIN
возвращает все строки из правой таблицы вместе с совпадающими строками из левой таблицы. Если в левой таблице нет соответствующих столбцов, она возвращаетNULL
значения.2.3 ПОЛНОЕ НАРУЖНОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ
Это
JOIN
сочетает в себеLEFT OUTER JOIN
иRIGHT OUTER JOIN
. Он возвращает строки из любой таблицы, когда выполняются условия, и возвращаетNULL
значение, если совпадения нет.Другими словами,
OUTER JOIN
основано на том факте, что: ДОЛЖНЫ быть перечислены ТОЛЬКО совпадающие записи в ОДНОЙ из таблиц (ВПРАВО или ВЛЕВО) или ОБА из таблиц (ПОЛНАЯ).3. ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ:
Он основан на двух условиях:
JOIN
производится по всем столбцам с тем же именем для равенства.Похоже, что это скорее теоретический характер, и в результате (вероятно) большинство СУБД даже не заботятся об этом.
4. CROSS JOIN:
Это декартово произведение двух задействованных таблиц. Результат
CROSS JOIN
не будет иметь смысла в большинстве ситуаций. Более того, нам это вообще не понадобится (или, если быть точным, нужно меньше всего).5. САМ СОЕДИНЯЙТЕСЬ:
Это не другая форма
JOIN
, скорее этоJOIN
(INNER
,OUTER
и т.д.) из таблицы к себе.СОЕДИНЕНИЯ на основе операторов
В зависимости от оператора, используемого для
JOIN
предложения, может быть два типаJOIN
s. Они есть1. Equi JOIN:
Для любого
JOIN
типа (INNER
,OUTER
и т. Д.), Если мы используем ТОЛЬКО оператор равенства (=), то мы говорим, что этоJOIN
являетсяEQUI JOIN
.2. Тета ПРИСОЕДИНЯЙТЕСЬ:
Это то же самое, что
EQUI JOIN
и другие операторы, такие как>, <,> = и т. Д.источник
Определение:
СОЕДИНЕНИЯ - это способ запроса данных, которые объединяются из нескольких таблиц одновременно.
Типы СОЕДИНЕНИЙ:
К СУБД относятся 5 типов соединений:
Equi-Join: объединяет общие записи из двух таблиц на основе условия равенства. Технически, соединение выполняется с использованием оператора равенства (=) для сравнения значений первичного ключа одной таблицы и значений внешнего ключа другой таблицы, поэтому набор результатов включает в себя общие (совпавшие) записи из обеих таблиц. Для реализации см. INNER-JOIN.
Natural-Join: это расширенная версия Equi-Join, в которой операция SELECT пропускает повторяющийся столбец. Для реализации см. INNER-JOIN
Non-Equi-Join: это обратное Equi-Join, где используется условие соединения, отличное от оператора равенства (=), например,! =, <=,> =,>, <Или BETWEEN и т. Д. Для реализации см. INNER-JOIN.
Self-Join: настраиваемое поведение объединения, когда таблица объединяется с самим собой; Как правило, это необходимо для запроса к самоссылающимся таблицам (или сущности унарных отношений). Для реализации см. ВНУТРЕННИЕ СОЕДИНЕНИЯ.
Декартово произведение: оно объединяет все записи обеих таблиц без каких-либо условий. Технически он возвращает набор результатов запроса без WHERE-предложения.
В соответствии с требованиями и усовершенствованиями SQL существует 3 типа объединений, и все объединения RDBMS могут быть достигнуты с помощью этих типов объединений.
INNER-JOIN: объединяет (или объединяет) совпадающие строки из двух таблиц. Сопоставление выполняется на основе общих столбцов таблиц и их операции сравнения. Если условие на основе равенства, то: EQUI-JOIN выполняется, в противном случае не-EQUI-Join.
OUTER-JOIN: объединяет (или объединяет) совпавшие строки из двух таблиц и несопоставленные строки со значениями NULL. Однако можно настроить выбор несопоставленных строк, например, выбрать несопоставленную строку из первой или второй таблицы по подтипам: LEFT OUTER JOIN и RIGHT OUTER JOIN.
2.1. LEFT Outer JOIN (он же LEFT-JOIN): возвращает совпадающие строки из двух таблиц и не совпадает только с таблицей LEFT (т. Е. С первой таблицей).
2.2. RIGHT Outer JOIN (он же RIGHT-JOIN): возвращает совпадающие строки из двух таблиц и не совпадает только с правой таблицей.
2,3. FULL OUTER JOIN (он же OUTER JOIN): возвращает совпадения и несоответствия из обеих таблиц.
CROSS-JOIN: это объединение не объединяет / объединяет, а выполняет декартово произведение.
Примечание: Self-JOIN может быть достигнуто с помощью INNER-JOIN, OUTER-JOIN и CROSS-JOIN в зависимости от требований, но таблица должна соединяться сама с собой.
Чтобы получить больше информации:
Примеры:
1.1: INNER-JOIN: реализация Equi-Join
1.2: INNER-JOIN: реализация Natural-JOIN
1.3: INNER-JOIN с реализацией NON-Equi-join
1.4: ВНУТРЕННЕЕ СОЕДИНЕНИЕ
2.1: НАРУЖНОЕ СОЕДИНЕНИЕ (полное внешнее соединение)
2.2: левое соединение
2.3: ПРАВИЛЬНОЕ СОЕДИНЕНИЕ
3.1: CROSS JOIN
3.2: CROSS JOIN-Self JOIN
//ИЛИ//
источник
intersect
/except
/union
; здесь кружки - это строки, возвращаемые символомleft
&right
join
, как говорят пронумерованные метки. Картинка AXB - это чепуха.cross join
=inner join on 1=1
& является частным случаем первой диаграммы.UNION JOIN
. Теперь устарел в SQL: 2003.Интересно, что большинство других ответов страдают от этих двух проблем:
Недавно я написал статью на эту тему: «Вероятно, неполное, всеобъемлющее руководство по множеству различных способов соединения таблиц в SQL» , которую я здесь кратко изложу.
Прежде всего: СОЕДИНЕНИЯ - это декартовы произведения
Вот почему диаграммы Венна объясняют их так неточно, потому что JOIN создает декартово произведение между двумя объединенными таблицами. Википедия это прекрасно иллюстрирует:
SQL синтаксис для декартовых продуктов
CROSS JOIN
. Например:Который объединяет все строки из одной таблицы со всеми строками из другой таблицы:
Источник:
Результат:
Если мы просто напишем список таблиц через запятую, мы получим то же самое:
ВНУТРЕННИЙ РЕЙТИНГ (Theta-JOIN)
An
INNER JOIN
- это просто фильтр,CROSS JOIN
где предикат фильтра вызываетсяTheta
в реляционной алгебре.Например:
Обратите внимание, что ключевое слово
INNER
является необязательным (кроме MS Access).( посмотрите на статью для примеров результатов )
EQUI JOIN
Специальный вид Theta-JOIN - это equi JOIN, который мы используем чаще всего. Предикат объединяет первичный ключ одной таблицы с внешним ключом другой таблицы. Если мы используем базу данных Sakila для иллюстрации, мы можем написать:
Это объединяет всех актеров с их фильмами.
Или также в некоторых базах данных:
USING()
Синтаксис позволяет указать столбец , который должен присутствовать на каждой стороне JOIN таблицы операции и создает предикат равенства этих двух столбцов.ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ
Другие ответы перечислили этот «тип JOIN» отдельно, но это не имеет смысла. Это просто синтаксическая форма сахара для equi JOIN, которая является частным случаем Theta-JOIN или INNER JOIN. НАТУРАЛЬНОЕ СОЕДИНЕНИЕ просто собирает все столбцы, которые являются общими для обеих объединяемых таблиц, и объединяет
USING()
эти столбцы. Что вряд ли пригодится из-за случайных совпадений (например,LAST_UPDATE
столбцы в базе данных Sakila ).Вот синтаксис:
НАРУЖНОЕ СОЕДИНЕНИЕ
Теперь
OUTER JOIN
немного отличается от того,INNER JOIN
как создаетUNION
несколько декартовых произведений. Мы можем написать:Никто не хочет писать последнее, поэтому мы пишем
OUTER JOIN
(что обычно лучше оптимизировать с помощью баз данных).Мол
INNER
, ключевое словоOUTER
здесь необязательно.OUTER JOIN
поставляется в трех вариантах:LEFT [ OUTER ] JOIN
: Левая таблицаJOIN
выражения добавляется в объединение, как показано выше.RIGHT [ OUTER ] JOIN
: Правая таблицаJOIN
выражения добавляется в объединение, как показано выше.FULL [ OUTER ] JOIN
: Обе таблицыJOIN
выражения добавляются в объединение, как показано выше.Все они могут быть объединены с ключевым словом
USING()
или сNATURAL
( у меня на самом деле был реальный пример использования дляNATURAL FULL JOIN
недавно )Альтернативные синтаксисы
В Oracle и SQL Server существует несколько устаревших синтаксисов, которые поддерживались
OUTER JOIN
еще до того, как стандарт SQL имел синтаксис для этого:Сказав это, не используйте этот синтаксис. Я просто перечислю это здесь, чтобы вы могли распознать его по старым постам в блоге / устаревшему коду.
Разделенный
OUTER JOIN
Мало кто знает это, но стандарт SQL определяет секционирование
OUTER JOIN
(и Oracle реализует это). Вы можете написать такие вещи:Части результата:
Дело здесь в том, что все строки с разделенной стороны объединения получат результат независимо от того,
JOIN
совпадает ли что- нибудь на «другой стороне соединения». Короче говоря: для заполнения редких данных в отчетах. Очень полезно!ПОЛУ СОЕДИНЕНИЕ
Шутки в сторону? Никакой другой ответ не получил это? Конечно, нет, потому что, к сожалению , он не имеет собственного синтаксиса в SQL (как ANTI JOIN ниже). Но мы можем использовать
IN()
иEXISTS()
, например, найти всех актеров, которые играли в фильмах:WHERE a.actor_id = fa.actor_id
Предикат действует как пол Предиката. Если вы не верите этому, проверьте планы выполнения, например, в Oracle. Вы увидите, что база данных выполняет операцию SEMI JOIN, а неEXISTS()
предикат.ANTI JOIN
Это как раз обратное SEMI JOIN ( будьте осторожны , чтобы не использовать ,
NOT IN
хотя , как это имеет важное предостережение)Вот все актеры без фильмов:
Некоторые люди (особенно люди из MySQL) также пишут ANTI JOIN так:
Я думаю, что историческая причина - производительность.
Боковое соединение
О, Боже, это слишком круто. Я единственный, кто упомянул это? Вот крутой запрос:
Он найдет ТОП-5 доходных фильмов на одного актера. Каждый раз, когда вам нужен запрос TOP-N-за-то,
LATERAL JOIN
будет вашим другом. Если вы человек SQL Server, то вы знаете этотJOIN
тип под именемAPPLY
Хорошо, возможно, это обман, потому что выражение
LATERAL JOIN
илиAPPLY
- это действительно «коррелированный подзапрос», который создает несколько строк. Но если мы допустим «коррелированные подзапросы», мы также можем говорить о ...MULTISET
Это реально реализовано только в Oracle и Informix (насколько мне известно), но его можно эмулировать в PostgreSQL с использованием массивов и / или XML и в SQL Server с использованием XML.
MULTISET
создает коррелированный подзапрос и вкладывает результирующий набор строк во внешний запрос. Приведенный ниже запрос выбирает всех актеров и для каждого актера собирает свои фильмы во вложенную коллекцию:Как вы уже видели, есть несколько типов JOIN , чем просто «скучно»
INNER
,OUTER
иCROSS JOIN
что, как правило , упоминаются. Подробнее в моей статье . И, пожалуйста, прекратите использовать диаграммы Венна, чтобы проиллюстрировать их.источник
Я создал иллюстрацию, которая объясняет лучше, чем слова, на мой взгляд:
источник
Я собираюсь нажать мою любимую мозоль: ключевое слово USING.
Если обе таблицы на обеих сторонах JOIN имеют правильные имена своих внешних ключей (т. Е. Одно и то же имя, а не просто «id»), то это можно использовать:
Я нахожу это очень практичным, читабельным и недостаточно часто используемым.
источник