Кроме того LEFT JOIN
, как RIGHT JOIN
и FULL JOIN
вписаться?
Кроме того LEFT JOIN
, как RIGHT JOIN
и FULL JOIN
вписаться?
Ответы:
Предполагается, что вы объединяете столбцы без дубликатов, что является очень распространенным случаем:
Внутреннее соединение A и B дает результат пересечения A B, то есть внутреннюю часть пересечения диаграммы Венна .
Внешнее объединение A и B дает результаты объединения B, то есть внешние части объединения диаграммы Венна.
Примеры
Предположим, у вас есть две таблицы с одним столбцом и данными следующим образом:
A B
- -
1 3
2 4
3 5
4 6
Обратите внимание, что (1,2) являются уникальными для A, (3,4) являются общими, и (5,6) являются уникальными для B.
Внутреннее соединение
Внутреннее соединение, использующее любой из эквивалентных запросов, дает пересечение двух таблиц, то есть двух общих строк, которые они имеют.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Левое внешнее соединение
Левое внешнее соединение даст все строки в A плюс все общие строки в B.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Правое внешнее соединение
Правое внешнее соединение даст все строки в B плюс все общие строки в A.
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
Полное внешнее соединение
Полное внешнее объединение даст вам объединение A и B, то есть всех строк в A и всех строк в B. Если что-то в A не имеет соответствующих данных в B, то часть B пуста, и порок наоборот.
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
Диаграммы Венна на самом деле не делают это для меня.
Например, они не показывают какого-либо различия между перекрестным соединением и внутренним соединением или, в более общем случае, показывают какое-либо различие между различными типами предикатов объединения или предоставляют основу для рассуждений о том, как они будут работать.
Ничто не заменит понимание логической обработки, и в любом случае это относительно просто понять.
on
предложение по всем строкам, начиная с шага 1, сохраняя те, в которых предикат оценивается какtrue
(Примечание: на практике оптимизатор запросов может найти более эффективные способы выполнения запроса, чем приведенное выше чисто логическое описание, но конечный результат должен быть таким же)
Я начну с анимированной версии полного внешнего соединения . Дальнейшее объяснение следует.
Исходные таблицы
Сначала начните с CROSS JOIN
(AKA декартово произведение). Это не имеет ON
предложения и просто возвращает каждую комбинацию строк из двух таблиц.
ВЫБЕРИТЕ А.ЦВЕТ, Б.ЦВЕТ ИЗ КРЕСТА СОЕДИНИТЕ B
Внутренние и внешние соединения имеют предикат предложения ON.
ВЫБЕРИТЕ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour
Выше классическое равное соединение.
Условие внутреннего соединения не обязательно должно быть условием равенства и не должно ссылаться на столбцы обеих (или даже обеих) таблиц. Оценка A.Colour NOT IN ('Green','Blue')
по каждому ряду результатов перекрестного соединения.
ВЫБЕРИТЕ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B ON 1 = 1
Условие соединения оценивается как true для всех строк в результате перекрестного соединения, так что это то же самое, что и перекрестное соединение. Я не буду повторять картину из 16 рядов снова.
Внешние объединения логически оцениваются так же, как и внутренние соединения, за исключением того, что если строка из левой таблицы (для левого объединения) вообще не объединяется ни с одной строкой из правой таблицы, она сохраняется в результате со NULL
значениями для правые колонны.
Это просто ограничивает предыдущий результат, возвращая только те строки, где B.Colour IS NULL
. В этом конкретном случае это будут строки, которые были сохранены, так как они не совпадали в правой таблице, и запрос возвращает одну красную строку, не совпадающую в таблице B
. Это известно как анти-полусоединение.
Важно выбрать столбец для IS NULL
теста, который не имеет значения NULL или для которого условие соединения гарантирует, что любые NULL
значения будут исключены, чтобы этот шаблон работал правильно, и избегал просто возвращать строки, которые, как оказалось, имеют NULL
значение для этого столбец в дополнение к несогласованным строкам.
Правые внешние объединения действуют аналогично левым внешним соединениям, за исключением того, что они сохраняют несоответствующие строки из правой таблицы и нулевые расширяют левые столбцы.
Полные внешние объединения объединяют поведение левого и правого объединений и сохраняют несовпадающие строки из левой и правой таблиц.
Строки в перекрестном соединении не соответствуют 1=0
предикату. Все строки с обеих сторон сохраняются с использованием обычных правил внешнего соединения с NULL в столбцах таблицы на другой стороне.
С незначительной поправкой к предыдущему запросу можно смоделировать одну UNION ALL
из двух таблиц.
Обратите внимание, что WHERE
предложение (если оно присутствует) логически выполняется после объединения. Одной из распространенных ошибок является выполнение левого внешнего соединения, а затем включение предложения WHERE с условием в правой таблице, которое заканчивается исключением несовпадающих строк. Вышеуказанное завершает выполнение внешнего соединения ...
... А затем выполняется предложение "Где". NULL= 'Green'
не оценивается как истина, поэтому строка, сохраненная внешним соединением, в конечном итоге отбрасывается (вместе с синим), эффективно преобразовывая соединение обратно во внутреннее.
Если бы целью было включить только строки из B, где Color - зеленый, и все строки из A независимо от правильного синтаксиса были бы
Посмотрите эти примеры в прямом эфире на SQLFiddle.com .
Объединения используются для объединения данных из двух таблиц, в результате чего получается новая временная таблица. Объединения выполняются на основе того, что называется предикатом, в котором указывается условие, используемое для выполнения объединения. Разница между внутренним соединением и внешним соединением заключается в том, что внутреннее объединение будет возвращать только те строки, которые действительно совпадают, основываясь на предикате соединения. Например, давайте рассмотрим таблицу Employee and Location:
Внутреннее объединение : - Внутреннее объединение создает новую таблицу результатов, комбинируя значения столбцов двух таблиц ( Employee и Location ) на основе предиката объединения. Запрос сравнивает каждую строку Employee с каждой строкой Location, чтобы найти все пары строк, которые удовлетворяют предикату соединения. Когда предикат соединения удовлетворяется путем сопоставления значений, отличных от NULL, значения столбцов для каждой соответствующей пары строк Employee и Location объединяются в результирующую строку. Вот как будет выглядеть SQL для внутреннего объединения:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Теперь вот как будет выглядеть результат выполнения SQL:
Внешнее соединение: - Для внешнего соединения не требуется, чтобы каждая запись в двух соединенных таблицах имела соответствующую запись. Объединенная таблица сохраняет каждую запись, даже если другой соответствующей записи не существует. Внешние объединения подразделяются далее на левые внешние и правые внешние объединения, в зависимости от того, какие строки таблицы сохраняются (левые или правые).
Левое внешнее соединение: - результат левого внешнего соединения (или просто левого соединения) для таблиц Employee и Location всегда содержит все записи «левой» таблицы ( Employee ), даже если условие соединения не находит подходящую запись в «Правильный» стол ( Location ). Вот как будет выглядеть SQL для левого внешнего соединения, используя таблицы выше:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Теперь вот как будет выглядеть результат выполнения этого SQL:
Правое внешнее соединение : - Правое внешнее соединение (или правое соединение) очень похоже на левое внешнее соединение, за исключением обработки обращенных таблиц. Каждая строка из «правой» таблицы ( Location ) появится в объединенной таблице хотя бы один раз. Если соответствующая строка из «левой» таблицы ( Employee ) не существует, в столбцах Employee появится NULLдля тех записей, которые не совпадают в Location . Вот как выглядит SQL:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Используя таблицы выше, мы можем показать, как будет выглядеть результирующий набор правого внешнего соединения:
Полные внешние соединения: - внешнее объединение: - Полное внешнее объединение или полное объединение - для сохранения несоответствующей информации путем включения несовпадающих строк в результаты объединения, используйте полное внешнее объединение. Он включает все строки из обеих таблиц, независимо от того, имеет ли другая таблица совпадающее значение.
Извлекать только совпадающие строки, то есть A intersect B
.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Выберите все записи из первой таблицы и все записи во второй таблице, которые соответствуют соединенным ключам.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Выберите все записи из второй таблицы и все записи в первой таблице, которые соответствуют соединенным ключам.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Простыми словами:
Внутреннее соединение извлекать только совпавшие строки.
Принимая во внимание, что внешнее соединение извлекает сопоставленные строки из одной таблицы и все строки в другой таблице .... результат зависит от того, какую из них вы используете:
Слева : соответствующие строки в правой таблице и все строки в левой таблице
Справа : соответствующие строки в левой таблице и все строки в правой таблице или
Полный : все строки во всех таблицах. Неважно, есть ли совпадение или нет
Внутреннее объединение показывает только строки, если на другой (правой) стороне объединения имеется соответствующая запись.
На (левом) внешнем соединении отображаются строки для каждой записи с левой стороны, даже если на другой (правой) стороне объединения нет совпадающих строк. Если соответствующей строки нет, столбцы для другой (правой) стороны будут показывать NULL.
Внутренние объединения требуют, чтобы в объединенной таблице существовала запись со связанным идентификатором.
Внешние объединения возвращают записи для левой стороны, даже если для правой стороны ничего не существует.
Например, у вас есть таблица Orders и OrderDetails. Они связаны "OrderID".
заказы
Информация для заказа
Запрос
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
будет возвращать только заказы, которые также имеют что-то в таблице OrderDetails.
Если вы измените его на OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
тогда он вернет записи из таблицы Orders, даже если у них нет записей OrderDetails.
Вы можете использовать это, чтобы найти Заказы, у которых нет OrderDetails, указывающего возможный потерянный заказ, добавив предложение where как WHERE OrderDetails.OrderID IS NULL
.
SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
в SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
(MySQL) с успехом. Я не был уверен насчет дополнительных условий, они хорошо сочетаются ...
Простыми словами:
Внутреннее соединение -> Возьмите ТОЛЬКО общие записи из родительской и дочерней таблиц, ГДЕ первичный ключ родительской таблицы соответствует внешнему ключу в дочерней таблице.
Осталось присоединиться ->
псевдокод
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Правое соединение : Точно противоположное левому соединению. Поместите имя таблицы в LEFT JOIN справа от правого соединения, вы получите тот же вывод, что и в LEFT JOIN.
Внешнее соединение : Показать все записи в обеих таблицахNo matter what
. Если записи в левой таблице не соответствуют правой таблице, основанной на первичном ключе, ключе Forieign, используйте значение NULL в качестве результата объединения.
Пример :
Предположим теперь для 2 таблиц
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Здесь таблица employee является главной таблицей, phone_numbers_employees является дочерней таблицей (она содержит emp_id
внешний ключ, который соединяет employee.id
ее с дочерней таблицей.)
Внутренние соединения
Принимайте записи только из 2 таблиц, ЕСЛИ если первичный ключ таблицы сотрудников (его идентификатор) совпадает с внешним ключом дочерней таблицы phone_numbers_employees (emp_id) .
Таким образом, запрос будет:
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Здесь берутся только совпадающие строки в первичном ключе = внешний ключ, как описано выше. Здесь несоответствующие строки в первичном ключе = внешний ключ пропускаются в результате объединения.
Левый присоединяется :
При левом соединении сохраняются все строки левой таблицы, независимо от того, есть ли строка, соответствующая правой таблице.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Внешние соединения :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Схематически это выглядит так:
Вы используете INNER JOIN
для возврата всех строк из обеих таблиц, где есть совпадение. т.е. в результирующей таблице все строки и столбцы будут иметь значения.
В OUTER JOIN
результирующей таблице могут быть пустые столбцы. Внешнее соединение может быть или LEFT
или RIGHT
.
LEFT OUTER JOIN
возвращает все строки из первой таблицы, даже если во второй таблице нет совпадений.
RIGHT OUTER JOIN
возвращает все строки из второй таблицы, даже если в первой таблице нет совпадений.
Это хорошее схематичное объяснение для всех видов соединений
источник: http://ssiddique.info/understanding-sql-joins-in-easy-way.html
INNER JOIN
требует, чтобы при сравнении двух таблиц было как минимум совпадение. Например, таблица A и таблица B, которые подразумевают A ٨ B (пересечение A B).
LEFT OUTER JOIN
а также LEFT JOIN
такие же. Это дает все записи, совпадающие в обеих таблицах и все возможности левой таблицы.
Аналогично RIGHT OUTER JOIN
и RIGHT JOIN
одинаковы. Это дает все записи, совпадающие в обеих таблицах и все возможности правой таблицы.
FULL JOIN
это комбинация LEFT OUTER JOIN
и RIGHT OUTER JOIN
без дублирования.
Ответ заключается в значении каждого, так и в результатах.
Примечание:
ВSQLite
не существуетRIGHT OUTER JOIN
илиFULL OUTER JOIN
.
А также вMySQL
нетFULL OUTER JOIN
.
Мой ответ основан на примечании выше .
Когда у вас есть две таблицы, подобные этим:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN:
Вы можете иметь все данные этих таблиц с CROSS JOIN
или просто ,
так:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
ВНУТРЕННЕЕ СОЕДИНЕНИЕ:
если вы хотите добавить фильтр к вышеуказанным результатам на основе отношения, которое table1.id = table2.id
вы можете использовать INNER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
LEFT [OUTER] JOIN:
Если вы хотите, чтобы все строки одной из таблиц в приведенном выше результате - с одинаковым отношением - вы можете использовать LEFT JOIN
:
(Для RIGHT JOIN просто измените место таблиц)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN:
Если вы также хотите, чтобы в ваших результатах были все строки другой таблицы, вы можете использовать FULL OUTER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Ну, так как вам нужно, вы выбираете каждый, который покрывает ваши потребности;).
full outer join
в MySQL ее тоже нет.
Внутреннее соединение.
Объединение объединяет строки из двух таблиц. Внутреннее объединение попыток , чтобы обеспечить соответствие двух таблиц на основе указанных критериев в запросе, и возвращает только те строки , которые совпадают. Если строка из первой таблицы в соединении совпадает с двумя строками во второй таблице, то в результатах будут возвращены две строки. Если в первой таблице есть строка, которая не соответствует строке во второй таблице, она не возвращается; аналогично, если во второй таблице есть строка, которая не соответствует строке в первой, она не возвращается.
Внешнее Присоединение.
Влево присоединиться попытками найти совпасть строки из первой таблицы , в строки во второй таблице. Если он не может найти совпадение, он вернет столбцы из первой таблицы и оставит столбцы из второй таблицы пустыми (пустыми).
INNER JOIN
наиболее типичное объединение для двух или более таблиц. Возвращает совпадение данных как для таблицы ON primarykey, так и для отношения forignkey.OUTER JOIN
так же, как INNER JOIN
, но он также включает в себя NULL
данные на ResultSet.
LEFT JOIN
= INNER JOIN
+ Несоответствующие данные левой таблицы с Null
совпадением на правой таблице.RIGHT JOIN
= INNER JOIN
+ Несоответствующие данные правой таблицы с Null
совпадением на левой таблице.FULL JOIN
= INNER JOIN
+ Несоответствующие данные в правой и левой таблицах с Null
совпадениями.INNER JOIN
и OUTER JOIN
мы можем написать запросы на самостоятельное соединение.Например:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
Я не вижу подробностей о производительности и оптимизаторе в других ответах.
Иногда полезно знать, что только INNER JOIN
ассоциативно, что означает, что оптимизатор имеет больше возможностей для игры с ним. Он может изменить порядок соединения, чтобы сделать его быстрее, сохраняя тот же результат. Оптимизатор может использовать большинство режимов соединения.
Как правило, рекомендуется использовать INNER JOIN
вместо разных видов соединений. (Конечно, если это возможно, учитывая ожидаемый набор результатов.)
Здесь есть несколько хороших примеров и объяснений об этом странном ассоциативном поведении:
INNER JOIN
это медленнее, чем LEFT JOIN
в большинстве случаев, и люди могут использовать LEFT JOIN
вместо INNER JOIN
добавления WHERE
для удаления неожиданных NULL
результатов;).
INNER
медленнее?
Покритиковав столь любимую диаграмму Венна в красных тонах, я подумал, что будет справедливо опубликовать мою собственную попытку.
Несмотря на то, что ответ @Martin Smith является лучшим из этой группы, он показывает только ключевые столбцы из каждой таблицы, в то время как я считаю, что в идеале также должны быть показаны неключевые столбцы.
Лучшее, что я мог бы сделать за полчаса, я все еще не думаю, что это адекватно показывает, что нулевые значения присутствуют из-за отсутствия значений ключей TableB
или что OUTER JOIN
это фактически объединение, а не соединение:
TableA a LEFT OUTER JOIN TableB b
наTableB B RIGHT OUTER JOIN TableA a
Точный алгоритм для INNER JOIN
, LEFT/RIGHT OUTER JOIN
являются следующие:
a
(a, b[i])
ON ...
предложение по каждой паре:ON( a, b[i] ) = true/false?
true
, вернуть эту объединенную строку (a, b[i])
.Outer Join
возвращает (виртуальную) пару, используя Null
для всех столбцов другой таблицы: (a, Null)
для внешнего соединения LEFT или (Null, b)
для внешнего соединения RIGHT. Это должно гарантировать, что все строки первой таблицы существуют в окончательных результатах.Примечание: условие, указанное в ON
предложении, может быть любым, необязательно использовать первичные ключи (и вам не нужно всегда ссылаться на столбцы из обеих таблиц)! Например:
... ON T1.title = T2.title AND T1.version < T2.version
(=> просмотреть этот пост в качестве примера использования: выберите только столбцы с максимальным значением в столбце )... ON T1.y IS NULL
... ON 1 = 0
(как образец)Примечание: левое соединение = левое внешнее соединение, правое соединение = правое внешнее соединение.
Простейшие определения
Внутреннее объединение: возвращает сопоставленные записи из обеих таблиц.
Полное внешнее объединение: возвращает сопоставленные и несопоставленные записи из обеих таблиц со значением NULL для несопоставленных записей из обеих таблиц .
Левое внешнее объединение: возвращает сопоставленные и несопоставленные записи только из таблицы на левой стороне .
Правое внешнее объединение: возвращает совпадающие и несопоставленные записи только из таблицы на правой стороне .
Короче говоря
Совпадение + Несоответствие слева + Несоответствие справа = Полное внешнее соединение
Совпадение + Левое Несоответствие = Левое внешнее соединение
Совпадение + Право Несоответствие = Право Наружное соединение
Matched = Inner Join
Проще говоря,
1. INNER JOIN ИЛИ EQUI JOIN: Возвращает набор результатов, который соответствует только условию в обеих таблицах.
2. ВНЕШНЕЕ СОЕДИНЕНИЕ: возвращает набор результатов всех значений из обеих таблиц, даже если условие соответствует или нет.
3. LEFT JOIN: возвращает набор результатов всех значений из левой таблицы и только строк, соответствующих условию в правой таблице.
4. RIGHT JOIN: возвращает набор результатов всех значений из правой таблицы и только строк, соответствующих условию в левой таблице.
5. ПОЛНОЕ СОЕДИНЕНИЕ: полное соединение и полное внешнее соединение - это одно и то же.
Примеры
Предположим, у вас есть две таблицы с одним столбцом и данными следующим образом:
A B
- -
1 3
2 4
3 5
4 6
7
8
Обратите внимание, что (1,2,7,8) являются уникальными для A, (3,4) являются общими и (5,6) являются уникальными для B.
Ключевое слово INNER JOIN выбирает все строки из обеих таблиц, если выполняется условие. Это ключевое слово создаст набор результатов путем объединения всех строк из обеих таблиц, где выполняется условие, т.е. значение общего поля будет одинаковым.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
Результат:
a | b
--+--
3 | 3
4 | 4
Это объединение возвращает все строки таблицы с левой стороны объединения и совпадающие строки для таблицы с правой стороны объединения. Строки, для которых нет подходящей строки на правой стороне, результирующий набор будет содержать нуль. LEFT JOIN также известен как LEFT OUTER JOIN
.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
Результат:
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
7 | null
8 | null
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
Результат:
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
ПОЛНОЕ (НАРУЖНОЕ) РЕШЕНИЕ :
FULL JOIN создает результирующий набор, комбинируя результат как LEFT JOIN, так и RIGHT JOIN. Результирующий набор будет содержать все строки из обеих таблиц. Строки, для которых нет соответствия, набор результатов будет содержать значения NULL.
select * from a FULL OUTER JOIN b on a.a = b.b;
Результат:
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
7 | null
8 | null
Внутреннее объединение - внутреннее объединение, использующее любой из эквивалентных запросов, дает пересечение двух таблиц , то есть двух общих строк, которые они имеют.
Левое внешнее соединение - левое внешнее соединение даст все строки в A, а также все общие строки в B.
Полное внешнее объединение - полное внешнее объединение даст вам объединение A и B, т.е. все строки в A и все строки в B. Если что-то в A не имеет соответствующего элемента в B, то часть B ноль, и наоборот
Join is not an intersection unless the tables have the same columns
Нет. Вы можете присоединиться к любым столбцам, которые вам нужны, и, если значение совпадает, они объединятся.
1. Внутреннее объединение: также называется присоединением. Возвращает строки, присутствующие как в левой, так и в правой таблице если есть совпадение . В противном случае он возвращает ноль записей.
Пример:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2. Полное внешнее соединение: также называется полным соединением. Он возвращает все строки, присутствующие как в левой таблице, так и в правой таблице.
Пример:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3. Левое внешнее соединение: или просто называется левым соединением. Он возвращает все строки, присутствующие в левой таблице и соответствующие строки из правой таблицы (если есть).
4. Правое внешнее соединение: также называется правым соединением. Он возвращает совпадающие строки из левой таблицы (если есть) и все строки, присутствующие в правой таблице.
Преимущества Joins
Рассмотрим ниже 2 таблицы:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
отдел
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
В основном написано как просто JOIN в SQL-запросах. Он возвращает только совпадающие записи между таблицами.
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
Как вы видите выше, Jose
не выводится из EMP на выходе, так как его dept_id 6
не находит соответствия в таблице Department. Аналогично HR
и R&D
строки не распечатываются из отдела таблицы , поскольку они не нашли соответствия в таблице EMP.
Таким образом, INNER JOIN или просто JOIN возвращает только совпадающие строки.
Это возвращает все записи из таблицы LEFT и только совпадающие записи из таблицы RIGHT.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
Таким образом, если вы наблюдаете вышеприведенный вывод, все записи из таблицы LEFT (Emp) печатаются с совпадающими записями из таблицы RIGHT.
HR
и R&D
строки не выводятся из таблицы Department, так как они не нашли соответствия в таблице Emp в dept_id.
Таким образом, LEFT JOIN возвращает ВСЕ строки из левой таблицы и только совпадающие строки из правой таблицы.
Также можете проверить ДЕМО здесь .
Пожалуйста , смотрите ответ на Мартина Смита за лучшие illustations и объяснения различных соединений, в том числе и в особенности различия между FULL OUTER JOIN
, RIGHT OUTER JOIN
и LEFT OUTER JOIN
.
Эти две таблицы образуют основу для представления JOIN
ниже:
SELECT *
FROM citizen
CROSS JOIN postalcode
Результатом будут декартовы произведения всех комбинаций. Никаких JOIN
условий не требуется:
INNER JOIN
так же, как просто: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
Результатом будут комбинации, удовлетворяющие требуемому JOIN
условию:
LEFT OUTER JOIN
такой же как LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
Результатом будет все, citizen
даже если нет совпадений postalcode
. Снова требуется JOIN
условие:
Все примеры были запущены на Oracle 18c. Они доступны на dbfiddle.uk, откуда также пришли скриншоты таблиц.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
JOIN
иWHERE
CROSS JOIN
в результате чего строки в качестве общей идеи / INNER JOIN
:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Использование CROSS JOIN
для получения результата LEFT OUTER JOIN
требует трюков, таких как добавление в NULL
строку. Это опущено.
INNER JOIN
становится декартовой продукцией. Это так же, как общая идея / CROSS JOIN
:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
Именно здесь внутреннее соединение действительно можно рассматривать как перекрестное соединение с результатами, не соответствующими удаленному условию. Здесь ни одна из полученных строк не удаляется.
Использование INNER JOIN
для получения результата LEFT OUTER JOIN
также требует хитростей. Это опущено.
LEFT JOIN
приводит к строкам как общая идея / CROSS JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN
приводит к строкам как общая идея / INNER JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
Поиск в интернете по изображению "sql join cross inner external" покажет множество диаграмм Венна. Раньше у меня была печатная копия одного на моем столе. Но есть проблемы с представительством.
Диаграмма Венна отлично подходит для теории множеств, где элемент может быть в одном или обоих наборах. Но для баз данных мне кажется, что элемент в одном «наборе» является строкой в таблице и, следовательно, не присутствует ни в каких других таблицах. Нет такой вещи, как одна строка присутствует в нескольких таблицах. Строка уникальна для таблицы.
Самостоятельные объединения - это угловой случай, когда каждый элемент фактически одинаков в обоих наборах. Но это все еще не свободно ни от одной из проблем ниже.
Набор A
представляет собой набор слева ( citizen
таблица), а набор B
- это набор справа ( postalcode
таблица) в обсуждении ниже.
Каждый элемент в обоих наборах сопоставляется с каждым элементом в другом наборе, что означает, что нам нужно A
количество каждого B
элемента и B
количество каждого A
элемента, чтобы правильно представить этот декартово произведение. Теория множеств не создана для нескольких идентичных элементов в наборе, поэтому я считаю, что диаграммы Венна правильно представляют ее непрактично / невозможно. Кажется, что это совсем не UNION
подходит.
Строки различны. Всего UNION
7 строк. Но они несовместимы для общего SQL
набора результатов. И это совсем не так CROSS JOIN
:
Попытка представить это так:
..но теперь это просто выглядит как INTERSECTION
, что это, конечно, нет . Кроме того, в этом элементе нет ни INTERSECTION
одного из двух различных наборов. Тем не менее, это очень похоже на результаты поиска, похожие на это:
Для справки один результат поиска для CROSS JOIN
s можно увидеть на Tutorialgateway . Как INTERSECTION
и этот, пуст.
Значение элемента зависит от JOIN
условия. Это можно представить при условии, что каждая строка становится уникальной для этого условия. Значение id=x
верно только для одного ряда. Как только строка в table A
( citizen
) соответствует нескольким строкам в table B
( postalcode
) при JOIN
условии, результат имеет те же проблемы, что и CROSS JOIN
: Строка должна быть представлена несколько раз, и теория множеств на самом деле не создана для этого. Хотя при условии уникальности диаграмма может работать, но имейте в виду, что это JOIN
условие определяет размещение элемента на диаграмме. Глядя только на значения JOIN
условия с остальной частью ряда только для поездки:
Это представление полностью расходится при использовании INNER JOIN
с ON 1 = 1
условием, превращающим его в CROSS JOIN
.
С self- JOIN
, строки на самом деле являются идентичными элементами в обеих таблицах, но представляют таблицы как обе A
и B
не очень подходят. Например , общее само JOIN
условие , которое делает элемент A
будет сопрягать иной элемент в В ON A.parent = B.child
, что делает матч с A
чтобы B
на отдельно элементах. Из примеров, которые будут SQL
похожи на это:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
То есть Смит - лидер и Грина, и Дженсена.
Опять проблемы начинаются, когда одна строка имеет несколько совпадений со строками в другой таблице. Это дополнительно усложняется тем, что OUTER JOIN
может соответствовать пустому набору. Но в теории множеств объединение любого множества C
и пустого множества всегда справедливо C
. Пустой набор ничего не добавляет. Представление этого LEFT OUTER JOIN
обычно просто показывает все, A
чтобы проиллюстрировать, что строки A
выбираются независимо от того, есть совпадение или нет B
. Однако у «совпадающих элементов» есть те же проблемы, что и на иллюстрации выше. Они зависят от состояния. И пустой набор, кажется, забрел к A
:
Нахождение всех строк CROSS JOIN
со Смитом и почтовым индексом на Луне:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Теперь диаграмма Венна не используется для отражения JOIN
. Используется только для WHERE
предложения:
... и это имеет смысл.
Как объяснил, это INNER JOIN
не совсем INTERSECT
. Однако INTERSECT
s можно использовать по результатам отдельных запросов. Здесь диаграмма Венна имеет смысл, поскольку элементы отдельных запросов на самом деле являются строками, которые либо принадлежат только одному из результатов, либо обоим. Очевидно, что Intersect будет возвращать результаты только в том случае, если строка присутствует в обоих запросах. Это SQL
приведет к тому же ряду, что и приведенный выше WHERE
, и диаграмма Венна также будет такой же:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
Ан OUTER JOIN
не а UNION
. Однако UNION
работают в тех же условиях INTERSECT
, что и возвращают все результаты, объединяющие оба параметра SELECT
:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
что эквивалентно:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..и дает результат:
Также здесь имеет смысл диаграмма Венна:
Важным примечанием является то, что они работают только тогда, когда структура результатов двух SELECT одинакова, что позволяет сравнивать или объединять. Результаты этих двух не позволят это:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
.. пытается объединить результаты с UNION
дает
ORA-01790: expression must have same datatype as corresponding expression
Для дальнейшего интереса прочитайте Скажите НЕТ диаграммам Венна при объяснении СОЕДИНЕНИЙ, и соединения sql как диаграмму Венна . Оба также покрывают EXCEPT
.
Здесь есть много хороших ответов с очень точными примерами реляционной алгебры . Вот очень упрощенный ответ, который может быть полезен для начинающих или начинающих программистов с дилеммами кодирования SQL.
В основном, чаще всего запросы JOIN
сводятся к двум случаям:
Для SELECT
подмножества данных A
:
INNER JOIN
когда связанные данные, которые B
вы ищете, ДОЛЖНЫ существовать для каждого проекта базы данных;LEFT JOIN
когда связанные данные, которые B
вы ищете MIGHT или MIGHT NOT, существуют для каждого проекта базы данных.Разница между inner join
и outer join
заключается в следующем:
Inner join
это объединение, объединяющее таблицы на основе совпадающих кортежей, тогда outer join
как объединение, объединяющее таблицы на основе сопоставленного и несопоставленного кортежа.Inner join
объединяет совпавшую строку из двух таблиц, в которой пропущены несопоставленные строки, тогда как outer join
объединяет строки из двух таблиц, и несопоставленные строки заполняются нулевым значением.Inner join
это как операция пересечения, тогда как outer join
это как операция объединения.Inner join
это два типа, тогда outer join
как три типа.outer join
быстрее чем inner join
.