Крім того, як це зробити 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) є унікальними для А, (3,4) є загальними, а (5,6) - унікальними для В.
Внутрішнє з'єднання
Внутрішнє з'єднання за допомогою будь-якого з еквівалентних запитів дає перетин двох таблиць, тобто двох рядків, які вони мають спільне.
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
пункту і просто повертає кожну комбінацію рядків з двох таблиць.
ВИБІРТЕ A.Colour, B.Colour ВІД КРОВНОГО ПРИЄДНАННЯ B
Внутрішні та зовнішні приєднання мають присудок "ON".
ВИБІРТЕ A.Колор, B.Колор ВІД ВНУТРІШНЬОГО ПРИЄДНАННЯ B НА A.Colour = B.Color
Сказане вище - класичне приєднання рівних.
Внутрішня умова з'єднання не обов'язково повинна бути умовою рівності, і вона не повинна посилати стовпці з обох (або навіть будь-яких) таблиць. Оцінювання A.Colour NOT IN ('Green','Blue')
в кожному рядку хрестоподібних прибутків.
ВИБІРТЕ A.Колор, B.Колор ВІД ВНУТРІШНЬОГО ПРИЄДНАННЯ В НА 1 = 1
Умова приєднання оцінюється як істинна для всіх рядків результату перехресного з'єднання, тому це точно так само, як і перехресне з'єднання. Я більше не повторюю картину з 16 рядів.
Зовнішні з'єднання логічно оцінюються так само, як і внутрішні з'єднання, за винятком того, що якщо рядок з лівої таблиці (для лівого з'єднання) взагалі не з'єднується з жодними рядками з таблиці правої руки, він зберігається в результаті зі NULL
значеннями для праві стовпці.
Це просто обмежує попередній результат лише повернення рядків там, де B.Colour IS NULL
. У цьому конкретному випадку це будуть збережені рядки, оскільки вони не збігаються в правій таблиці, а запит повертає єдиний червоний рядок, не узгоджений у таблиці B
. Це відомо як анти-півфінальне приєднання.
Важливо вибрати стовпець для IS NULL
тесту, який або не є нульовим, або для якого умова з'єднання гарантує, що будь-які NULL
значення будуть виключені для того, щоб цей шаблон працював правильно і уникав просто повернення рядків, які, можливо, мають NULL
значення для цього стовпця на додаток до незрівняних рядків.
Праві зовнішні з'єднання діють аналогічно лівим зовнішнім з'єднанням, за винятком того, що вони зберігають невідповідні рядки з правої таблиці та нульові розширення лівих стовпців.
Повне зовнішнє з'єднання поєднує в собі поведінку лівого та правого з'єднань та зберігає невідповідні рядки з лівої та правої таблиць.
Жоден рядок у хресті не поєднується з 1=0
присудком. Усі рядки з обох сторін зберігаються, використовуючи звичайні правила зовнішнього з'єднання з NULL у стовпцях таблиці з іншого боку.
З незначною поправкою до попереднього запиту можна було б імітувати a UNION ALL
з двох таблиць.
Зауважте, що WHERE
пункт (якщо він присутній) логічно працює після з'єднання. Однією поширеною помилкою є виконання лівого зовнішнього з'єднання, а потім включити пункт WHERE з умовою в правій таблиці, що закінчується, виключаючи невідповідні рядки. Вищезазначене закінчується виконанням зовнішнього з'єднання ...
... А далі запускається пункт "Куди". NULL= 'Green'
не оцінюється як істинне, тому рядок, збережений зовнішнім з'єднанням, закінчується відкинутим (разом із синім), фактично перетворюючи з'єднання назад у внутрішній.
Якби намір включав лише рядки з B, де колір є зеленим, а всі рядки з A незалежно від правильного синтаксису.
Дивіться ці приклади, які працюють у прямому ефірі на SQLFiddle.com .
Об'єднання використовуються для об'єднання даних з двох таблиць, результатом чого є нова, тимчасова таблиця. Приєднання здійснюються на основі чогось, що називається присудком, який визначає умову, яку потрібно використовувати для здійснення приєднання. Різниця між внутрішнім з'єднанням і зовнішнім з'єднанням полягає в тому, що внутрішнє з'єднання поверне лише ті рядки, які насправді відповідають на основі предиката приєднання. Наприклад - Розглянемо таблицю працівників та місцеположення:
Внутрішнє приєднання : - Внутрішнє з'єднання створює нову таблицю результатів, поєднуючи значення стовпців двох таблиць ( Співробітник та Місцезнаходження ) на основі предиката приєднання. Запит порівнює кожен рядок Співробітника з кожним рядком Місцеположення, щоб знайти всі пари рядків, які задовольняють присудок приєднання. Коли присудок-присудок задовольняється зіставленням значень, що не стосуються 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:
Зовнішнє з'єднання : - Зовнішнє з'єднання не вимагає, щоб кожен запис у двох об'єднаних таблицях мав відповідні записи. Об'єднана таблиця зберігає кожен запис, навіть якщо не існує іншої відповідної записи. Зовнішні з'єднання підрозділяються далі на ліві зовнішні з'єднання та праві зовнішні з'єднання, залежно від того, які рядки таблиці зберігаються (зліва або справа).
Лівий зовнішній приєднання : - Результат лівого зовнішнього з'єднання (або просто ліве з'єднання) для таблиць Співробітник та Місцерозташування завжди містять усі записи таблиці "ліворуч" ( Співробітник ), навіть якщо умова приєднання не знаходить жодної відповідності запису в "правильна" таблиця ( Розташування ). Ось як виглядатиме SQL для лівого зовнішнього з'єднання, використовуючи таблиці вище:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Тепер ось як виглядатиме результат запуску цього SQL:
Праве зовнішнє з'єднання : - праве зовнішнє з'єднання (або праве з'єднання) сильно нагадує ліве зовнішнє з'єднання, за винятком випадків, коли обробка таблиць перевернута. Кожен рядок із "правої" таблиці ( Місцезнаходження ) відображатиметься в таблиці об'єднаних принаймні один раз Якщо не існує відповідного рядка з таблиці "зліва" ( Співробітник ), NULL з'явиться у стовпцях від " Співробітник" для тих записів, які не відповідають місцеположенню . Ось як виглядає 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
Простими словами:
An Внутрішнє з'єднання витягувати тільки збіглися рядки.
В той час, як зовнішнє з'єднання вилучення відповідних рядків з однієї таблиці та всіх рядків в іншій таблиці .... результат залежить від того, який ви використовуєте:
Зліва : відповідні рядки в правій таблиці та всі рядки в лівій таблиці
Правильно : відповідні рядки в лівій таблиці та всі рядки в правій таблиці або
Повне : Усі рядки у всіх таблицях. Не має значення, чи є відповідність чи ні
Внутрішнє з'єднання показує рядки лише у тому випадку, якщо на іншій (правій) стороні з'єднання є запис відповідності.
Зовнішнє з'єднання (ліворуч) показує рядки для кожного запису з лівої сторони, навіть якщо на іншій (правій) стороні з'єднання немає відповідних рядків. Якщо немає відповідного рядка, стовпці для іншої (правої) сторони показуватимуть NULL.
Внутрішні об'єднання вимагають, щоб запис із пов’язаним ідентифікатором існував у об'єднаній таблиці.
Зовнішнє з'єднання поверне записи для лівого боку, навіть якщо для правого боку нічого не існує.
Наприклад, у вас є таблиця Orders і OrderDetails. Вони пов'язані "OrderID".
Замовлення
Деталі замовлення
Запит
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
поверне лише Замовлення, у яких також є щось у таблиці OrderDetails.
Якщо ви зміните його на ВНУТРІШНІЙ ЛІВ, ПРИЄДНАЙТЕ
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
тоді він поверне записи з таблиці Замовлення, навіть якщо у них немає записів OrderDetails.
Ви можете використовувати це для пошуку Замовлень, у яких немає жодних OrderDetails, що вказують на можливий осиротілий наказ, додавши пункт, як 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.
}
}
Правий приєднання : прямо навпроти лівого з’єднання. Помістіть назву таблиці вліво ПРИЄДНАЙТЕ з правого боку в Право приєднавшись, ви отримаєте такий же вихід, як і ВЛЕВОГО ПРИЄДНАННЯ.
Зовнішнє приєднання : Показати всі записи в обох таблицях No matter what
. Якщо записи в таблиці зліва не відповідають правильній таблиці на основі первинного, ключа Forieign, використовуйте значення NULL як результат з'єднання.
Приклад:
Давайте тепер припустимо для 2-х таблиць
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Тут таблиця співробітників - головна таблиця, 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 ПРИЄДНАЙТЕСЬ:
Ви можете мати всі дані цих таблиць з таким 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 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
:
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.
Внутрішнє з'єднання.
З’єднання - це поєднання рядків з двох таблиць. Внутрішнє об'єднання спроб , щоб забезпечити відповідність двох таблиць на основі зазначених критеріїв у запиті, і повертає тільки ті рядки , які збігаються. Якщо рядок з першої таблиці в з'єднанні збігається з двома рядами в другій таблиці, то два результати будуть повернуті в результатах. Якщо в першій таблиці є рядок, який не відповідає рядку у другій, він не повертається; також, якщо у другій таблиці є рядок, який не відповідає рядку в першій, він не повертається.
Зовнішнє приєднання.
Вліво приєднатися спробами знайти збігтися рядки з першої таблиці , в рядки в другій таблиці. Якщо він не може знайти збіг, він поверне стовпці з першої таблиці і залишить стовпці з другої таблиці порожніми (null).
INNER JOIN
найбільш типове з'єднання для двох або більше таблиць. Він повертає збіг даних як у таблиці ON, первинний ключ, так і відношення 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
(так само, як зразок)Примітка: Ліве з'єднання = Ліве зовнішнє приєднання, праве приєднання = Праве зовнішнє приєднання.
Найпростіші визначення
Внутрішня приєднання: Повертає відповідні записи з обох таблиць.
Повне зовнішнє приєднання: Повертає відповідні та незрівнянні записи з обох таблиць з нулем для невідповідних записів з обох таблиць .
Left Outer Join: Повертає відповідні та незрівняні записи лише з таблиці з лівого боку .
Права зовнішня приєднання: Повертає відповідні та не збігаються записи лише з таблиці з правого боку .
Коротко
Збіг + Ліворуч Незрівнянний + Правий Незрівняний = Повне зовнішнє приєднання
Збіг + Ліворуч Незрівнянний = Лівий зовнішній приєднання
Збіг + Право Незрівняно = Правий зовнішній приєднання
Збіг = Внутрішнє приєднання
Простіше кажучи,
1. ВНУТРІШНЕ ПРИЄДНАННЯ ДО ЕКВІ: Повертає результатів, що відповідає лише умові в обох таблицях.
2. ЗОВНІШНЕ ПРИЄДНАННЯ: Повертає набір результатів усіх значень з обох таблиць, навіть якщо є відповідність умовам чи ні.
3. ПРИЄДНАЙТЕСЬ ЛІВО: Повертає набір результатів усіх значень з лівої таблиці та лише рядки, які відповідають умові в правій таблиці.
4. ПРАВО ПРИЄДНАЙТЕСЬ: Повертає набір результатів усіх значень з правої таблиці та лише рядки, які відповідають умові в лівій таблиці.
5. ПОВНИЙ ПРИЄДНАЙТЕСЬ: Повне приєднання та повне зовнішнє приєднання є однаковими.
Приклади
Припустимо, у вас є дві таблиці з кожним стовпцем та даними наступних даних:
A B
- -
1 3
2 4
3 5
4 6
7
8
Зауважимо, що (1,2,7,8) властиві А, (3,4) є загальними, а (5,6) - унікальними для В.
Ключове слово 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
Це з'єднання повертає всі рядки таблиці з лівого боку об'єднання та відповідні рядки таблиці з правого боку з'єднання. Рядки, для яких у правій частині немає відповідного рядка, набір результатів міститиме null. Лівий приєднання також відомий як 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 створює набір результатів, поєднуючи результат як ВЛІСТЬ ПРИЄДНАЙТЕСЬ, так і ПРАВО ПРИЄДНАЙТЕСЬ. Набір результатів буде містити всі рядки з обох таблиць. Рядки, для яких немає відповідності, набір результатів будуть містити значення 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. Правий зовнішній приєднання: також називається як право приєднання. Він повертає відповідні рядки з лівої таблиці (якщо такі є), і всі рядки, присутні в правій таблиці.
Переваги приєднань
Розглянемо нижче 2 таблиці:
ЕМП
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
В основному пишеться як ПРИЄДНАЙТЕСЬ у запитах 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
не знайде відповідності в таблиці Відділення. Так само HR
і R&D
рядки не друкуються з відділу таблиці оскільки вони не знайшли відповідності в таблиці Emp.
Отже, INNER JOIN або просто ПРИЄДНАЙТЕ, повертає лише відповідні рядки.
Це повертає всі записи з таблиці Вліво і лише відповідні записи з таблиці ПРАВО.
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
Отже, якщо ви дотримуєтесь вищенаведеного результату, всі записи з таблиці ВЛЕВО (Emp) друкуються із відповідними записами з таблиці ВПРАВО.
HR
і R&D
рядки не друкуються з таблиці відділу, оскільки вони не знайшли відповідності в таблиці Emp на dept_id.
Отже, LEFT JOIN повертає ВСІ рядки з лівої таблиці та лише відповідні рядки з таблиці ВПРАВО.
Також можна перевірити DEMO тут .
Будь ласка , дивіться відповідь на Мартіна Сміта за кращі illustations і пояснення різних з'єднань, в тому числі і в особливості відмінності між FULL OUTER JOIN
, RIGHT OUTER JOIN
і LEFT OUTER JOIN
.
Ці дві таблиці є основою для подання наведених JOIN
нижче s:
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 приєднатися до хреста внутрішнього зовнішнього" покаже безліч діаграм Венна. У мене на столі був друкований примірник одного. Але з представництвом є проблеми.
Діаграма Венна відмінно підходить для теорії множин, де елемент може бути в одному або обох множинах. Але для баз даних мені здається, що елемент в одному "наборі" є рядком у таблиці, а тому й не присутній в жодних інших таблицях. Немає такої речі, як один ряд присутній у кількох таблицях. Ряд унікальний для таблиці.
Самоз'єднання - це кутовий випадок, коли кожен елемент насправді однаковий у обох наборах. Але це все ще не позбавлене жодного із наведених нижче питань.
Множина A
представляє набір зліва ( citizen
таблиця), а набір B
- це праворуч ( postalcode
таблиця) в нижній частині обговорення.
Кожен елемент в обох наборах узгоджується з кожним елементом в іншому наборі, а значить, нам потрібна A
кількість кожного B
елемента та B
кількість кожного A
елемента, щоб правильно представити цей декартовий продукт. Теорія множин не створена для декількох однакових елементів у наборі, тому я вважаю, що діаграми Венна належним чином представляють це непрактично / неможливо. Здається, це зовсім не UNION
підходить.
Рядки виразні. Усього UNION
7 рядків. Але вони несумісні для загального SQL
набору результатів. І це зовсім не так, як CROSS JOIN
працює:
Намагаємось представити це так:
..а тепер це просто виглядає як INTERSECTION
, чого, звичайно, немає . Крім того, немає жодного елемента, INTERSECTION
що є насправді в жодному з двох різних наборів. Однак це дуже схоже на результати пошуку, схожі на це:
Для довідки один результат пошуку для CROSS JOIN
s можна побачити на Tutorialgateway . Точно так INTERSECTION
само, як і цей, порожній.
Значення елемента залежить від JOIN
умови. Це можна представити за умови, що кожен рядок стає унікальним для цієї умови. Значення id=x
вірно лише для одного ряду. Після того, як рядок у таблиці A
( citizen
) відповідає умові декількох рядків у таблиці B
( postalcode
) JOIN
, результат має ті самі проблеми, що і CROSS JOIN
: Рядок потрібно представляти кілька разів, і теорія наборів насправді для цього не створена. За умови унікальності діаграма може працювати, хоча і майте на увазі, що JOIN
умова визначає розміщення елемента в діаграмі. Дивлячись лише на значення JOIN
стану з рештою ряду просто поруч:
Це уявлення повністю розпадається при використанні INNER JOIN
з ON 1 = 1
умовою, що перетворює його в a CROSS JOIN
.
З само- JOIN
, рядки, насправді idential елементів в обох таблицях, але представляють таблиці , як і 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 може бути використаний за результатами окремих запитів. Тут діаграма Венна має сенс, тому що елементи окремих запитів насправді є рядками, які або належать лише одному з результатів, або обом. Пересікання, очевидно, поверне результати лише тоді, коли рядок присутній в обох запитах. Це SQL
призведе до того ж рядка, що і вище WHERE
, і діаграма Venn також буде такою ж:
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
s:
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
Для подальшої зацікавленості читайте « Скажіть ні» для діаграм Венна, коли пояснення JOINs і sql приєднується як діаграма venn . Обидва також охоплюють EXCEPT
.
Тут є багато хороших відповідей з дуже точними прикладами реляційної алгебри . Ось дуже спрощена відповідь, яка може бути корисною для любителів або початківців кодерів із дилемами кодування SQL.
В основному, запити JOIN
зводяться до двох випадків:
Для SELECT
підмножини даних A
:
INNER JOIN
коли відповідні дані, які B
ви шукаєте, ОБОВ'ЯЗКОВО існують для розробки баз даних;LEFT JOIN
коли пов'язані дані, які B
ви шукаєте, МОЖЛИВО або МОЖЛИВО НЕ існують для дизайну бази даних.Різниця між inner join
та outer join
полягає в наступному:
Inner join
є об'єднанням, що поєднує таблиці, засновані на збігу кортежів, тоді як outer join
є об'єднанням та комбінованою таблицею, заснованої як на зібраному кордоні, так і на незрівняному кортежі.Inner join
зливає відповідні рядки з двох таблиць, у яких пропущений незрівнянний рядок, тоді як outer join
злиття рядків з двох таблиць і невідповідних рядків заповнюють нульовим значенням.Inner join
це як операція перетину, тоді outer join
як операція об'єднання.Inner join
це два типи, тоді outer join
як три типи.outer join
швидше, ніж inner join
.