Яка різниця між "ВНУТРІШНЄ ПРИЄДНАННЯ" та "ВНУТРІШНЕ ПРИЄДНАННЯ"?


4670

Крім того, як це зробити LEFT JOIN, RIGHT JOINі FULL JOINвписатись?


63
З відповідей та коментарів та їх посилань нижче лише одна насправді пояснює, як діаграми Venn представляють операторів: Область перетину кола представляє набір рядків у ПРИЄДНАЙТЕСЬ B. Область, унікальна для кожного кола, являє собою набір рядків, які ви отримуєте, беручи його рядки таблиці, які не беруть участі в A JOIN B, і додають стовпці, унікальні до іншої таблиці, усі встановлені на NULL. (І більшість дає розпливчасту фіктивну кореспонденцію гуртків А і В.)
philipxy

1
Скачучи з теоретичних відповідей нижче, до реальної програми: Я часто працюю з експериментальними даними, використовуючи орієнтири на процесорі. Часто я хочу порівнювати результати між 2 або більше апаратними опціями. INNER JOIN означає, що я бачу лише ті показники, які успішно працювали у всіх експериментах; OUTER JOIN означає, що я бачу всі експерименти, включаючи ті, які не вдалося виконати в деяких конфігураціях. Важливо бачити невдачі в таких експериментах, а також успіхи. Досить важливо, що я написав PerlSQL, щоб отримати зовнішній приєднання, коли його не вистачало багатьом RDBMS,
Krazy Glew

4
Дуже багато відповідей уже надано, але я не бачив цього підручника. Якщо ви знаєте діаграми Венна, це ВЕЛИКИЙ підручник: blog.codinghorror.com/a-visual-explanation-of-sql- приєднується, для мене достатньо стисло, щоб швидко прочитати, але все-таки розуміє всю концепцію і працює все справи дуже добре. Якщо ви не знаєте, що таке діаграми Венна - вивчіть їх. Для цього потрібно 5-10 хвилин і допоможе вам, коли вам потрібно візуалізувати роботу з наборами та керувати операціями над наборами.
DanteTheSmith

14
@DanteTheSmith Ні, це страждає від тих же проблем, що і діаграми тут. Дивіться мій коментар вище щодо питання та нижче про цю саму публікацію в блозі: "Джефф відхиляє свій блог на кілька сторінок в коментарях". Діаграми Венна показують елементи у множинах. Просто спробуйте визначити, що саме є множинами та якими є елементи на цих діаграмах. Набори - це не таблиці, а елементи - не їхні рядки. Також можна з'єднати будь-які дві таблиці, тож ПК та ФК є нерелевантними. Все невдало. Ви робите тільки те , що тисячі інших зробили - отримали невиразне враження ви (помилково) вважати , має сенс.
філіппі

3
Кріс, я рекомендую вам ознайомитись із цією статтею: спрямовано до datatascience.com/… ... і подумайте про те, щоб змінити свій вибір прийнятої відповіді (можливо, на ту, що з нагодою) на відповідь, яка не використовує діаграми Венна. В даний час прийнята відповідь вводить в оману занадто багато людей. Я закликаю вас зробити це для блага нашої громади та якості нашої бази знань.
Колм Бхандал

Відповіді:


6111

Якщо припустити, що ви приєднуєтесь до стовпців без дублікатів, що є дуже поширеним випадком:

  • Внутрішнє з'єднання 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

41
Добре було б доповнити приклад, додавши ще один рядок у таблиці В зі значенням 4. Це покаже, що внутрішні з’єднання не повинні бути рівними, не мають рядків.
softveda

472
Відмінне пояснення, проте це твердження: Зовнішнє з'єднання A і B дає результати A з'єднання B, тобто зовнішніх частин об'єднання діаграми Венна. не сформульовано точно. Зовнішнє з'єднання дасть результати A пересічення B на додаток до одного з наступних: все A (ліве з'єднання), усе B (праворучне з'єднання) або все A і все B (повне з'єднання). Тільки цей останній сценарій насправді є об'єднанням B. Все-таки добре написане пояснення.
Томас

11
Я маю рацію, що ПОВНИЙ ПРИЄДНАЙТЕ є псевдонімом ПОВНОГО ВИХІДНОГО ПРИЄДНАННЯ, а ЛІВНЕ ПРИЄДНАННЯ - псевдонім LEFT OUTER JOIN?
Даміан

3
так, чудове і відмінне пояснення. але чому в стовпці b значення не в порядку? тобто 6,5 не так 5,6?
Амеєр

7
@Ameer, спасибі Приєднання не гарантує замовлення, вам потрібно буде додати пункт ORDER BY.
Марк Гаррісон

731

Діаграми Венна насправді це не роблять для мене.

Наприклад, вони не показують різниці між перехресним з'єднанням та внутрішнім з'єднанням, або, загалом, не показують різниці між різними типами предиката приєднання або не надають основи для міркування про те, як вони будуть діяти.

Існує ніякої заміни для розуміння логічної обробки, і це зрозуміло порівняно просто.

  1. Уявіть хрестовий з’єднання.
  2. Оцініть onзастереження щодо всіх рядків з кроку 1, зберігаючи ті, де присудок оцінюєtrue
  3. (Лише для зовнішніх з'єднань) додайте назад у будь-які зовнішні рядки, які були втрачені на кроці 2.

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

Почну з анімованої версії повного зовнішнього з'єднання . Подальше пояснення випливає.

введіть тут опис зображення


Пояснення

Джерельні таблиці

введіть опис посилання тут

Спочатку почніть з CROSS JOIN(декартівського продукту AKA). Тут немає ONпункту і просто повертає кожну комбінацію рядків з двох таблиць.

ВИБІРТЕ A.Colour, B.Colour ВІД КРОВНОГО ПРИЄДНАННЯ B

введіть опис посилання тут

Внутрішні та зовнішні приєднання мають присудок "ON".

  • Внутрішнє з'єднання. Оцініть умову в пункті "УВІМКНЕНО" для всіх рядків результату перехресного з'єднання. Якщо вірно, поверніть об'єднаний рядок. Інакше відмовтеся від нього.
  • Залишилося зовнішнє приєднання. Те саме, що внутрішнє з'єднання, то для будь-яких рядків у лівій таблиці, які нічого не відповідають результатам, мають значення NULL для стовпців правої таблиці.
  • Справа назовні. Те саме, що внутрішнє з'єднання, то для будь-яких рядків у правій таблиці, які нічого не відповідають, виводять ці значення з NULL для лівих стовпців таблиці.
  • Повне зовнішнє приєднання. Те саме, що і внутрішній приєднання, тоді збережіть ліві не збігаються рядки, як у лівому зовнішньому з’єднанні та правому невідповідному рядку відповідно до правого зовнішнього з'єднання.

Деякі приклади

ВИБІРТЕ A.Колор, B.Колор ВІД ВНУТРІШНЬОГО ПРИЄДНАННЯ B НА A.Colour = B.Color

Сказане вище - класичне приєднання рівних.

Внутрішнє з'єднання

Анімована версія

введіть тут опис зображення

ВИБІРТЕ A.Колор, B.Колор із внутрішнього приєднання B до A.Colorur NOT IN ("Зелений", "Синій")

Внутрішня умова з'єднання не обов'язково повинна бути умовою рівності, і вона не повинна посилати стовпці з обох (або навіть будь-яких) таблиць. Оцінювання A.Colour NOT IN ('Green','Blue')в кожному рядку хрестоподібних прибутків.

внутрішній 2

ВИБІРТЕ A.Колор, B.Колор ВІД ВНУТРІШНЬОГО ПРИЄДНАННЯ В НА 1 = 1

Умова приєднання оцінюється як істинна для всіх рядків результату перехресного з'єднання, тому це точно так само, як і перехресне з'єднання. Я більше не повторюю картину з 16 рядів.

ВИБІРТЕ A.Колор, B.Колор із лівого зовнішнього з'єднання B на A.Colour = B.Color

Зовнішні з'єднання логічно оцінюються так само, як і внутрішні з'єднання, за винятком того, що якщо рядок з лівої таблиці (для лівого з'єднання) взагалі не з'єднується з жодними рядками з таблиці правої руки, він зберігається в результаті зі NULLзначеннями для праві стовпці.

LOJ

ВИБІРТЕ A.Колор, B.Колор ВІД ЛІТУШЬОГО ВНУТРІШНЬОГО ПРИЄДНАННЯ В НА А.Колор = B.Колор, де БУДЬ ЦВЕТ НУЛЬНИЙ

Це просто обмежує попередній результат лише повернення рядків там, де B.Colour IS NULL. У цьому конкретному випадку це будуть збережені рядки, оскільки вони не збігаються в правій таблиці, а запит повертає єдиний червоний рядок, не узгоджений у таблиці B. Це відомо як анти-півфінальне приєднання.

Важливо вибрати стовпець для IS NULLтесту, який або не є нульовим, або для якого умова з'єднання гарантує, що будь-які NULLзначення будуть виключені для того, щоб цей шаблон працював правильно і уникав просто повернення рядків, які, можливо, мають NULLзначення для цього стовпця на додаток до незрівняних рядків.

loj є нульовим

ВИБІРТЕ A.Колор, B.Колор ВІД ПРАВИШОГО ВНУТРІШНЬОГО ПРИЄДНАННЯ B НА A.Colour = B.Color

Праві зовнішні з'єднання діють аналогічно лівим зовнішнім з'єднанням, за винятком того, що вони зберігають невідповідні рядки з правої таблиці та нульові розширення лівих стовпців.

ROJ

ВИБІРТЕ A.Колор, B.Колор ВІД ПОВНОГО ВНУТРІШНЬОГО ПРИЄДНАННЯ B НА A.Colour = B.Color

Повне зовнішнє з'єднання поєднує в собі поведінку лівого та правого з'єднань та зберігає невідповідні рядки з лівої та правої таблиць.

FOJ

ВИБІРТЕ A.Колор, B.Колор ВІД ПОВНОГО ВНУТРІШНЬОГО ПРИЄДНАННЯ B НА 1 = 0

Жоден рядок у хресті не поєднується з 1=0присудком. Усі рядки з обох сторін зберігаються, використовуючи звичайні правила зовнішнього з'єднання з NULL у стовпцях таблиці з іншого боку.

FOJ 2

ВИБІРТЕ КОАЛЕССЮ (A.Colour, B.Colour) ЯК Колір ВІДПОВІДНОГО ВИКОРИСТАННЯ B Приєднайтесь до B = 1 = 0

З незначною поправкою до попереднього запиту можна було б імітувати a UNION ALLз двох таблиць.

СОЮЗ ВСІХ

ВИБІРТЕ A.Колор, B.Колор від лівого зовнішнього приєднання до B

Зауважте, що WHEREпункт (якщо він присутній) логічно працює після з'єднання. Однією поширеною помилкою є виконання лівого зовнішнього з'єднання, а потім включити пункт WHERE з умовою в правій таблиці, що закінчується, виключаючи невідповідні рядки. Вищезазначене закінчується виконанням зовнішнього з'єднання ...

LOJ

... А далі запускається пункт "Куди". NULL= 'Green'не оцінюється як істинне, тому рядок, збережений зовнішнім з'єднанням, закінчується відкинутим (разом із синім), фактично перетворюючи з'єднання назад у внутрішній.

LOJtoInner

Якби намір включав лише рядки з B, де колір є зеленим, а всі рядки з A незалежно від правильного синтаксису.

ВИБІРТЕ A.Колор, B.Колор із лівого зовнішнього з'єднання B на A.Colour = B.Colour AND B.Colour = 'Зелений'

введіть тут опис зображення

SQL Fiddle

Дивіться ці приклади, які працюють у прямому ефірі на SQLFiddle.com .


46
Я скажу, що, хоча це не працює для мене майже так само добре, як діаграми Венна, я розумію, що люди змінюються і вчаться по-різному, і це дуже добре представлене пояснення на відміну від будь-якого, що я бачив раніше, тому підтримую @ypercube в присудження бонусних балів. Також хороша робота, що роз'яснює різницю внесення додаткових умов у пункт JOIN проти пункту WHERE. Кудо вам, Мартін Сміт.
Старий Про

22
@OldPro Діаграми Венна в порядку, наскільки вони йдуть, я думаю, але вони мовчать про те, як представити перехресне з'єднання або диференціювати один вид предиката приєднання, наприклад, приєднання еквівалента від іншого. Ментальна модель оцінки предиката приєднання в кожному рядку результату перехресного з'єднання, а потім додавання назад у незрівняних рядках, якщо зовнішнє з'єднання, і, нарешті, оцінка місця, де для мене краще працює.
Мартін Сміт

18
Діаграми Венна хороші для представлення об'єднань та перехресть та відмінностей, але не приєднуються. Вони мають незначне освітнє значення для дуже простих приєднань, тобто приєднань, де умова приєднання знаходиться на унікальних стовпцях.
ypercubeᵀᴹ

12
@Arth - Ні, ти не прав. SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 це те, що діаграми Венна не можуть проілюструвати.
Мартін Сміт

7
@MartinSmith Вау, я згоден, я абсолютно помиляюся! Надто звик працювати з людиною .. дякую за виправлення.
Арт

187

Об'єднання використовуються для об'єднання даних з двох таблиць, результатом чого є нова, тимчасова таблиця. Приєднання здійснюються на основі чогось, що називається присудком, який визначає умову, яку потрібно використовувати для здійснення приєднання. Різниця між внутрішнім з'єднанням і зовнішнім з'єднанням полягає в тому, що внутрішнє з'єднання поверне лише ті рядки, які насправді відповідають на основі предиката приєднання. Наприклад - Розглянемо таблицю працівників та місцеположення:

введіть тут опис зображення

Внутрішнє приєднання : - Внутрішнє з'єднання створює нову таблицю результатів, поєднуючи значення стовпців двох таблиць ( Співробітник та Місцезнаходження ) на основі предиката приєднання. Запит порівнює кожен рядок Співробітника з кожним рядком Місцеположення, щоб знайти всі пари рядків, які задовольняють присудок приєднання. Коли присудок-присудок задовольняється зіставленням значень, що не стосуються 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

Використовуючи наведені вище таблиці, ми можемо показати, як виглядатиме набір результатів правого зовнішнього з'єднання:

введіть тут опис зображення

Повне зовнішнє приєднання: - Повне зовнішнє приєднання або повне приєднання - це збереження незрівнянної інформації, включення невідмінних рядків до результатів з'єднання, використання повного зовнішнього з'єднання. Він включає всі рядки з обох таблиць, незалежно від того, має інша таблиця відповідне значення.

Джерело зображення

Посібник для MySQL 8.0 - приєднайтесь до синтаксису

Операції приєднання Oracle


3
найкраща відповідь поки що, альтернативний синтаксис - ось що я шукав, дякую!
Джої

1
Діаграми Венна неправильно позначені. Дивіться мої коментарі до питання та інші відповіді. Також більшість цієї мови є бідними. Напр .: "Коли присудок-присудок задовольняється зіставленням значень, що не належать до NULL, значення стовпців для кожної збіжної пари рядків Співробітник та Місце розташування об'єднуються в результатний рядок." Ні, не "Коли присудок-присудок задовольняється зіставленням значень, що не стосуються NULL". Значення рядків не мають значення, крім того, чи є умова в цілому справжньою чи помилковою. Деякі значення цілком можуть бути NULL для справжнього стану.
філіпсі

Хоча це прямо не вказано, діаграми в цьому діаграмі є діаграми Венна. Діаграми Венна, як правило, не є правильною математичною характеристикою з'єднання. Я пропоную зняти діаграми Венна.
Колм Бхандал

@ColmBhandal: вилучено діаграми Венна
ajitksharma

Будь ласка, використовуйте текст, а не зображення / посилання, для тексту - включаючи таблиці та ERD . Використовуйте зображення лише для того, що неможливо виразити як текст, або для збільшення тексту. Зображення не можна шукати, вирізати та вставляти. Додайте легенду / ключ та пояснення із зображенням.
філіпсі

132

Внутрішнє з'єднання

Отримайте лише відповідні рядки, тобто 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

Список літератури


14
Як називається інструмент? Мені здається, що це цікаво, оскільки він показує кількість рядків та вен-діаграм
Grijesh Chauhan

2
@GrijeshChauhan Так, але ви можете спробувати запустити це за допомогою вина .
Тушар Гупта - curioustushar

2
Ох! так, я .. Я використовував SQLyog, використовуючи вино .. є також PlayOnLinux
Grijesh Chauhan

1
Ваш текст незрозумілий і неправильний. "Лише зіставлені рядки" - це рядки з перехресного з'єднання A&B & те, що отримано (Внутрішнє з'єднання B) - це не перетин B, а (ліве з'єднання B), що перетинається (праве з'єднання B). "Вибрані" рядки не з A&B, вони з A cross join B & з нульових значень рядків від A & B.
philipxy

@ TusharGupta-curioustushar слід включити "Таблиці, які використовуються для прикладів SQL"
Мануель Йордан

111

Простими словами:

An Внутрішнє з'єднання витягувати тільки збіглися рядки.

В той час, як зовнішнє з'єднання вилучення відповідних рядків з однієї таблиці та всіх рядків в іншій таблиці .... результат залежить від того, який ви використовуєте:

  • Зліва : відповідні рядки в правій таблиці та всі рядки в лівій таблиці

  • Правильно : відповідні рядки в лівій таблиці та всі рядки в правій таблиці або

  • Повне : Усі рядки у всіх таблицях. Не має значення, чи є відповідність чи ні


1
@nomen Не те, що ця відповідь відповідає на нього, але ВНУТРІШНЕ ПРИЄДНАННЯ є перетином, і ПОЛНЕ ВИХІД ПРИЄДНАННЯ - відповідний СПІЛЬНІСТЬ, якщо лівий і правий набори / кола містять рядки (відповідно) ВЛІТЬКИЙ ТА ПРАВО PS Ця відповідь незрозуміла щодо рядків введення та виводу. Він плутає "в лівій / правій таблиці" з "має ліву / праву частину вліво / вправо", і він використовує "зіставлений рядок" проти "всі", щоб означати рядок, розширений на рядок з іншої таблиці проти нулів.
філіпсі

103

Внутрішнє з'єднання показує рядки лише у тому випадку, якщо на іншій (правій) стороні з'єднання є запис відповідності.

Зовнішнє з'єднання (ліворуч) показує рядки для кожного запису з лівої сторони, навіть якщо на іншій (правій) стороні з'єднання немає відповідних рядків. Якщо немає відповідного рядка, стовпці для іншої (правої) сторони показуватимуть NULL.


81

Внутрішні об'єднання вимагають, щоб запис із пов’язаним ідентифікатором існував у об'єднаній таблиці.

Зовнішнє з'єднання поверне записи для лівого боку, навіть якщо для правого боку нічого не існує.

Наприклад, у вас є таблиця Orders і OrderDetails. Вони пов'язані "OrderID".

Замовлення

  • OrderID
  • Ім'я клієнта

Деталі замовлення

  • OrderDetailID
  • 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.


1
Я ціную простий, але реалістичний приклад. Я успішно змінив запит, як 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). Я не був впевнений у додаткових умовах, вони добре змішуються ...
PhiLho

68

Простими словами:

Внутрішнє приєднання -> Візьміть ТОЛЬКІ загальні записи з батьківських та дочірніх таблиць, де первинний ключ батьківської таблиці відповідає зовнішньому ключу дочірньої таблиці.

Лівий приєднання ->

псевдо-код

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;

Діаграматично це виглядає так:

Діаграма


4
Результат не має нічого спільного з первинними / унікальними / ключовими ключами та зовнішніми ключами. Поведінку можна і потрібно описати без посилання на них. Розраховується перехресне з'єднання, потім фільтруються рядки, що не відповідають умові ON; додатково для зовнішніх рядків з'єднання відфільтровані / незрівняні рядки розширюються на NULL (на ліворуч / праворуч /
повне

Припущення, що приєднання SQL - це завжди збіг первинних / зовнішніх ключів, призводить до цього неправильного використання діаграм Венна. Будь ласка, перегляньте відповідь відповідно.
Колм Бхандал

58

Ти використовуєш INNER JOIN для повернення всіх рядків з обох таблиць, де є відповідність. тобто в отриманій таблиці всі рядки та стовпці матимуть значення.

У OUTER JOINотриманій таблиці можуть бути порожні стовпці. Зовнішнє приєднання може бути LEFTабо RIGHT.

LEFT OUTER JOIN повертає всі рядки з першої таблиці, навіть якщо у другій таблиці немає збігів.

RIGHT OUTER JOIN повертає всі рядки з другої таблиці, навіть якщо в першій таблиці немає збігів.



54

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без нього.


43

Відповідь полягає в значенні кожного, так і в результатах.

Примітка:
У 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.
Поташин

35

Внутрішнє з'єднання.

З’єднання - це поєднання рядків з двох таблиць. Внутрішнє об'єднання спроб , щоб забезпечити відповідність двох таблиць на основі зазначених критеріїв у запиті, і повертає тільки ті рядки , які збігаються. Якщо рядок з першої таблиці в з'єднанні збігається з двома рядами в другій таблиці, то два результати будуть повернуті в результатах. Якщо в першій таблиці є рядок, який не відповідає рядку у другій, він не повертається; також, якщо у другій таблиці є рядок, який не відповідає рядку в першій, він не повертається.

Зовнішнє приєднання.

Вліво приєднатися спробами знайти збігтися рядки з першої таблиці , в рядки в другій таблиці. Якщо він не може знайти збіг, він поверне стовпці з першої таблиці і залишить стовпці з другої таблиці порожніми (null).


28

введіть тут опис зображення

  • 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збігами.
  • Самозаключення не є ключовим словом у SQL, коли таблиця посилається на дані сама по собі відома як самопоєднання. Використовуючи 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 

27

Я не бачу багато деталей щодо продуктивності та оптимізатора в інших відповідях.

Іноді добре це знати лише INNER JOIN асоціативний характер, що означає, що оптимізатор має найбільшу можливість грати з ним. Він може змінити порядок з'єднання, щоб швидше зберігати той же результат. Оптимізатор може використовувати найбільш приєднані режими.

Як правило, це хороша практика намагатися використовувати INNER JOINзамість різного виду приєднань. (Звичайно, якщо можливо, враховуючи очікуваний набір результату.)

Тут є кілька хороших прикладів та пояснень щодо цієї дивної асоціативної поведінки:


4
Це не може бути "хорошою практикою" використовувати один тип з'єднання над іншим. Яке приєднання ви використовуєте, визначає потрібні вам дані. Якщо ви використовуєте інший, ви неправі. Плюс, в Oracle принаймні ця відповідь є абсолютно неправильною. Це звучить зовсім неправильно, і у вас немає доказів. У вас є докази?
Бен

1. Я маю на увазі спробувати використовувати. Я бачив, що багато людей, які використовують лівий зовні, приєднуються скрізь без поважних причин. (З'єднані стовпці були "не нульовими".) У тих випадках було б краще використовувати з'єднання INNER. 2. Я додав посилання, що пояснює неасоціативну поведінку краще, ніж я міг.
Лайош Верес

Як я знаю, INNER JOINце повільніше, ніж LEFT JOINу більшості випадків, і люди можуть використовувати LEFT JOINзамість того INNER JOIN, щоб додати додаток WHEREдля видалення несподіваних NULLрезультатів;).
shA.t

Ці коментарі зробили мене трохи невпевнено. Як ви думаєте, чому INNERце повільніше?
Лайош Верес

Залежить від двигуна. gnu join, приєднувальні клавіші, DB2, MySQL. Пастки для продуктивності мають велику кількість, наприклад, друге введення тексту або чітке відтворення.
mckenzm

26

Розкритикувавши улюблену діаграму Венна з червоним відтінком, я подумав, що справедливо розмістити власну спробу.

Хоча відповідь @Martin Smith є найкращою з цієї групи довгий шлях, він показує лише ключовий стовпець з кожної таблиці, тоді як я думаю, що в ідеалі також повинні бути показані стовпчики, що не є ключовими.

Найкраще, що я міг зробити за дозволену півгодини, я все ще не думаю, що це адекватно показує, що нулі існують через відсутність ключових значень у TableBабо, що OUTER JOINнасправді є об'єднанням, а не об'єднанням:

введіть тут опис зображення


2
Питання задає різницю між приєднаннями INNER та OUTER, але не обов'язково залишати зовнішнє приєднання lol
LearnByReading

@LearnByReading: моє фото праворуч є праве зовнішнє з'єднання ІЕ замінити TableA a LEFT OUTER JOIN TableB bзTableB B RIGHT OUTER JOIN TableA a
onedaywhen

26

Точний алгоритм INNER JOIN, LEFT/RIGHT OUTER JOINє наступні:

  1. Візьміть кожен рядок із першої таблиці: a
  2. Розгляньте всі рядки з другої таблиці біля неї: (a, b[i])
  3. Оцініть ON ...застереження проти кожної пари:ON( a, b[i] ) = true/false?
    • Коли умова оцінюється true, поверніть цей об'єднаний рядок (a, b[i]).
    • Коли ви досягнете кінця другої таблиці без відповідності, і це Outer Joinповернення (віртуальної) пари, використовуючи Nullдля всіх стовпців іншої таблиці: (a, Null)для зовнішнього з'єднання LEFT або (Null, b)для зовнішнього RIGHT. Це означає, що всі рядки першої таблиці існують у кінцевих результатах.

Примітка: умова, зазначена в ONпункті, може бути будь-якою, не потрібно використовувати первинні ключі (і вам не потрібно завжди посилатися на стовпці з обох таблиць)! Наприклад:

Внутрішній приєднання проти лівого зовнішнього приєднання


введіть тут опис зображення

Примітка: Ліве з'єднання = Ліве зовнішнє приєднання, праве приєднання = Праве зовнішнє приєднання.


20

Найпростіші визначення

Внутрішня приєднання: Повертає відповідні записи з обох таблиць.

Повне зовнішнє приєднання: Повертає відповідні та незрівнянні записи з обох таблиць з нулем для невідповідних записів з обох таблиць .

Left Outer Join: Повертає відповідні та незрівняні записи лише з таблиці з лівого боку .

Права зовнішня приєднання: Повертає відповідні та не збігаються записи лише з таблиці з правого боку .

Коротко

Збіг + Ліворуч Незрівнянний + Правий Незрівняний = Повне зовнішнє приєднання

Збіг + Ліворуч Незрівнянний = Лівий зовнішній приєднання

Збіг + Право Незрівняно = Правий зовнішній приєднання

Збіг = Внутрішнє приєднання


1
Це геніально і пояснює, чому приєднання не працює так, як очікувалося для індексу часових рядів. Часові позначки одна секунда однакові.
yeliabsalohcin

1
@yeliabsalohcin Ви не пояснюєте "як очікувалося" тут або "працює" у своєму коментарі до питання. Це просто деякі незрозумілі особисті помилки, яких ти дивно очікуєш від інших. Якщо ви ставитесь до слів як неохайно, коли читаєте - неправильно трактуєте чітке письмо та / або приймаєте нечітке письмо - як коли ви пишете тут, тоді ви можете сподіватися на помилки. Насправді ця відповідь, як і більшість тут, незрозуміла та неправильна. "Внутрішня приєднання: повертає відповідні записи з обох таблиць" неправильно, коли набори стовпців вводу відрізняються. Він намагається сказати певне що - то, але це НЕ . (Дивіться мою відповідь.)
philipxy

9

Простіше кажучи,

1. ВНУТРІШНЕ ПРИЄДНАННЯ ДО ЕКВІ: Повертає результатів, що відповідає лише умові в обох таблицях.

2. ЗОВНІШНЕ ПРИЄДНАННЯ: Повертає набір результатів усіх значень з обох таблиць, навіть якщо є відповідність умовам чи ні.

3. ПРИЄДНАЙТЕСЬ ЛІВО: Повертає набір результатів усіх значень з лівої таблиці та лише рядки, які відповідають умові в правій таблиці.

4. ПРАВО ПРИЄДНАЙТЕСЬ: Повертає набір результатів усіх значень з правої таблиці та лише рядки, які відповідають умові в лівій таблиці.

5. ПОВНИЙ ПРИЄДНАЙТЕСЬ: Повне приєднання та повне зовнішнє приєднання є однаковими.


5

У SQL є основні, головним чином, 2 типи ПРИЄДНАННЯ: [ІННЕР І ВНУТРІШНІЙ]


Приклади

Припустимо, у вас є дві таблиці з кожним стовпцем та даними наступних даних:

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

1
Діаграми Венна недостатньо, щоб описати приєднання SQL в загальному випадку. Приєднання SQL не обов'язково повинні відповідати рядки між таблицями один на один, наприклад, використовуючи зовнішній ключ та первинний ключ.
Колм Бхандал

Як ви з'єднаєте 2 таблиці без відповідності рядка? Потрібно мати первинний або зовнішній ключ стовпця або якесь загальне поле, щоб ви могли виконати приєднання. Мені цікаво, чому ви спростували цю відповідь. І діаграма Venn - це джерело, яке пояснює, як працює SQL JOIN. Чи є якісь кращі приклади для представлення приєднань? Якщо ні, будь ласка, підсиліть їх, щоб люди отримували кращі рішення. Дякую.
Mayur

Ви ставите діаграми в дописі. Яка легенда для діаграм? - Які елементи кожного набору? А як щодо того, що столики - це сумки, а не набори? Ви не кажете. Одне, що вони не є наборами, це рядки A&B на етикетках. Дивіться мої коментарі до публікацій на цій сторінці. Цей пост просто сліпо повторює неправильне використання, яке бачили в інших місцях, але не зрозуміли і не поставили під сумнів. Також те, що ви говорите в тексті тут, є незрозумілим і неправильним. Крім того, це нічого не додає до багатьох відповідей тут. (Незважаючи на те, що майже всі є досить бідними.) PS Будь ласка, уточнюйте за допомогою редагувань, а не коментарів.
філіппі

ФК не потрібні для приєднання чи запиту. Будь-які 2 таблиці можуть бути об'єднані за будь-яких умов, що включають їх стовпці, і незалежно від будь-яких обмежень, тригерів чи тверджень.
філіпсі

3
  • Внутрішнє з'єднання - Внутрішнє з'єднання за допомогою будь-якого з еквівалентних запитів дає перетин двох таблиць , тобто двох рядків, які вони мають спільне.

  • Лівий зовнішній з’єднання - лівий зовнішній з’єднання дасть усі рядки в A, плюс будь-які загальні рядки в B.

  • Повне зовнішнє з'єднання - Повне зовнішнє з'єднання дасть вам об'єднання A і B, тобто всі рядки в A і всі рядки в B. Якщо щось у A не має відповідної дати в B, то частина B є нульовий, і навпаки


1
Це і неправильно, і незрозуміло. Приєднання не є перетином, якщо таблиці не мають однакових стовпців. Зовнішні приєднання не мають рядків з A або B, якщо вони не мають однакових стовпців, і в цьому випадку не додаються нулі. Ви намагаєтесь щось сказати, але ви цього не говорите. Ви не пояснюєте правильно чи чітко.
філіпсі

@philipxy: Не погоджуючись у вашій заяві. Join is not an intersection unless the tables have the same columnsНі. Ви можете приєднатися до будь-яких потрібних вам стовпців, і якщо значення збігається, вони приєднаються разом.
SuicideSheep

Цей коментар такий же неясний, як і ваша відповідь. (Я припускаю, що ви можете думати щось на зразок. Набір значень підпорядкування для загальних стовпців результату є перетином наборів значень підпорядкування для загальних стовпців кожного з входів; але це не те, що ви написали. незрозуміло.)
philipxy

Я мав на увазі, що з'єднання - це лише перетин входів, коли це природне внутрішнє з'єднання входів з тими ж стовпцями. Ви неправильно вживаєте слова "перехрестя" та "союз".
філіпсі

3

1. Внутрішня приєднання: Також називається як Приєднатися. Він повертає рядки, присутні як у лівій таблиці, так і в правій таблиці, лише якщо є відповідність . В іншому випадку він повертає нульові записи.

Приклад:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
INNER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

вихід1

2. Повне зовнішнє приєднання: також називається повним приєднанням. Він повертає всі рядки, присутні як в лівій, так і в правій таблиці.

Приклад:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
FULL OUTER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

вихід2

3. Лівий зовнішній приєднання: або просто викликається як ліве з'єднання . Він повертає всі рядки, присутні в лівій таблиці, і відповідні рядки з правої таблиці (якщо такі є).

4. Правий зовнішній приєднання: також називається як право приєднання. Він повертає відповідні рядки з лівої таблиці (якщо такі є), і всі рядки, присутні в правій таблиці.

приєднується

Переваги приєднань

  1. Виконується швидше.

2
Це правильно лише тоді, коли таблиці мають однаковий набір стовпців. (Це плутає внутрішнє з'єднання з перетином і повне з'єднання з союзом.) Також "відповідність" не визначена. Прочитайте інші мої коментарі.
philipxy

2

Розглянемо нижче 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 тут .


2

Загальна ідея

Будь ласка , дивіться відповідь на Мартіна Сміта за кращі illustations і пояснення різних з'єднань, в тому числі і в особливості відмінності між FULL OUTER JOIN, RIGHT OUTER JOINі LEFT OUTER JOIN.

Ці дві таблиці є основою для подання наведених JOINнижче s:

Основа

КРОВИЙ ПРИЄДНАЙТЕ

CrossJoin

SELECT *
  FROM citizen
 CROSS JOIN postalcode

Результатом стануть декартові вироби всіх комбінацій. Не JOINпотрібна умова:

CrossJoinResult

ВНУТРІШНЄ З'ЄДНАННЯ

INNER JOIN те саме, що просто: JOIN

Внутрішнє з'єднання

SELECT *
  FROM citizen    c
  JOIN postalcode p ON c.postal = p.postal

Результатом стануть комбінації, які відповідають необхідній JOINумові:

InnerJoinResult

ЛІВНІЙ ЗОВНІШНІ ПРИЄДНАЙТЕ

LEFT OUTER JOIN те саме, що LEFT JOIN

Ліворуч

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal

Результатом буде все, citizenнавіть якщо в матчі немає матчів postalcode. Знову необхідна JOINумова:

LeftJoinResult

Дані для гри

Усі приклади представлені на 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підходить.

Рядки виразні. Усього UNION7 рядків. Але вони несумісні для загального SQLнабору результатів. І це зовсім не так, як CROSS JOINпрацює:

CrossJoinUnion1

Намагаємось представити це так:

CrossJoinUnion2Crossing

..а тепер це просто виглядає як INTERSECTION, чого, звичайно, немає . Крім того, немає жодного елемента, INTERSECTIONщо є насправді в жодному з двох різних наборів. Однак це дуже схоже на результати пошуку, схожі на це:

CrossJoinUnionUnion3

Для довідки один результат пошуку для CROSS JOINs можна побачити на Tutorialgateway . Точно так INTERSECTIONсамо, як і цей, порожній.

ВНУТРІШНЄ З'ЄДНАННЯ

Значення елемента залежить від JOINумови. Це можна представити за умови, що кожен рядок стає унікальним для цієї умови. Значення id=xвірно лише для одного ряду. Після того, як рядок у таблиці A( citizen) відповідає умові декількох рядків у таблиці B( postalcode) JOIN, результат має ті самі проблеми, що і CROSS JOIN: Рядок потрібно представляти кілька разів, і теорія наборів насправді для цього не створена. За умови унікальності діаграма може працювати, хоча і майте на увазі, що JOINумова визначає розміщення елемента в діаграмі. Дивлячись лише на значення JOINстану з рештою ряду просто поруч:

InnerJoinIntersection - заповнене

Це уявлення повністю розпадається при використанні 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

SelfJoinResult

Значить Сміт є лідером як Зеленого, так і Дженсена.

ЗОВНІШНЕ ПРИЄДНАЙТЕСЬ

Знову проблеми починаються, коли в одному рядку є кілька збігів із рядками в іншій таблиці. Це ще більше ускладнюється тим, що OUTER JOINможе відповідати порожньому набору. Але в теорії множин об'єднання будь-якого набору Cі порожнього набору завжди справедливе C. Порожній набір нічого не додає. Уявлення про це, LEFT OUTER JOINяк правило, лише показує все, Aщоб проілюструвати, що рядки в Aобрані незалежно від того, є збіг чи ні B. Однак "відповідні елементи" мають ті самі проблеми, що і на наведеній вище ілюстрації. Вони залежать від стану. І порожній набір, схоже, перекинувся на A:

LeftJoinIntersection - заповнене

ДЕ ЗАКЛАД - має сенс

Пошук усіх рядків CROSS JOINіз Сміта та поштового індексу на Місяці:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   AND p.area = 'Moon';

Де - результат

Тепер діаграма Венна не використовується для відображення JOIN. Він використовується лише для WHEREпункту:

Де

..і це має сенс.

Коли INTERSECT і UNION має сенс

ІНТЕРСЕКТ

Як пояснили INNER JOIN, насправді це не так INTERSECT. Однак INTERSECTs може бути використаний за результатами окремих запитів. Тут діаграма Венна має сенс, тому що елементи окремих запитів насправді є рядками, які або належать лише одному з результатів, або обом. Пересікання, очевидно, поверне результати лише тоді, коли рядок присутній в обох запитах. Це 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, що і призводить до повернення всіх результатів, поєднуючи обидва SELECTs:

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.


1

Тут є багато хороших відповідей з дуже точними прикладами реляційної алгебри . Ось дуже спрощена відповідь, яка може бути корисною для любителів або початківців кодерів із дилемами кодування SQL.

В основному, запити JOINзводяться до двох випадків:

Для SELECTпідмножини даних A:

  • використовувати, INNER JOINколи відповідні дані, які Bви шукаєте, ОБОВ'ЯЗКОВО існують для розробки баз даних;
  • використовувати, LEFT JOINколи пов'язані дані, які Bви шукаєте, МОЖЛИВО або МОЖЛИВО НЕ існують для дизайну бази даних.

1

Різниця між inner joinта outer joinполягає в наступному:

  1. Inner joinє об'єднанням, що поєднує таблиці, засновані на збігу кортежів, тоді як outer joinє об'єднанням та комбінованою таблицею, заснованої як на зібраному кордоні, так і на незрівняному кортежі.
  2. Inner joinзливає відповідні рядки з двох таблиць, у яких пропущений незрівнянний рядок, тоді як outer joinзлиття рядків з двох таблиць і невідповідних рядків заповнюють нульовим значенням.
  3. Inner joinце як операція перетину, тоді outer joinяк операція об'єднання.
  4. Inner joinце два типи, тоді outer joinяк три типи.
  5. outer joinшвидше, ніж inner join.

1
Результат зовнішнього з'єднання такий же, як внутрішній приєднання, але плюс кілька додаткових рядків, тому я не маю поняття, чому ви думаєте, чому зовнішнє з'єднання було б швидшим. Також які ці "два типи" внутрішнього з'єднання? Я припускаю, що ви маєте на увазі повну, ліву і праву для зовнішніх?
Мартін Сміт

1
@ M.achaibou Будь ласка, не вносьте правки, які вносять непотрібні зміни формату. Імена операторів не є кодом, якщо вони не використовуються в коді. Будь ласка, не вносьте змін у зміст публікації, опублікуйте коментар автору. Якщо у вас немає представника, тоді зачекайте, поки ви це зробите. Буває, що плакат це схвалив, але просимо не вносити таких змін. PS Зовнішнє з'єднання не швидше, ніж внутрішнє з'єднання.
філіпсі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.