MySQL: Швидке розбиття типів приєднань


157

Мені б хотілося швидко розбити типи приєднань MySQL. Я знаю про них, решта я не впевнений, що вони означають.

  • кома відокремлена (для чого саме це коротке?)SELECT * FROM a, b WHERE b.id = a.beeId AND ...
  • показати інформацію від a, навіть якщо в b немає відповідностей: SELECT * FROM a LEFT OUTER JOIN b ON b.id = a.beeId WHERE ...

Я бачив інші приєднання, але хочу знати, що робить їх різними, що таке INNER/ OUTERчи додає LEFTзміни.

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


Відповіді:


463

3
+1, але обидва відсутні cross join, що є декартовим продуктом.
Дені де Бернарді

11
@denis: ознайомтеся ближче за посиланням codinghorror.com:There's also a cartesian product or cross join, which as far as I can tell, can't be expressed as a Venn diagram:
Rufinus

1
Я вражений, роздрукувавши ці діаграми і поклавши її на стіну свого офісу. ти змінив моє життя!
йоссіко

41
Питання стосується конкретно MySQL. MySQL не підтримує приєднання FULL OUTER.
Майк Баранчак

4
і, звичайно, це має бути причиною не публікувати цю графіку. зітхання
Руфінус

27

На основі Вашого коментаря, прості визначення кожного найкраще можна знайти в W3Schools . Перший рядок кожного типу дає коротке пояснення типу приєднання

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

END EDIT

У двох словах, приклад, який ви подали з комою, відокремлював комами

SELECT * FROM a, b WHERE b.id = a.beeId AND ...

- це вибір кожного запису з таблиць a і b з комами, що розділяють таблиці, це може бути використано також у стовпцях типу

SELECT a.beeName,b.* FROM a, b WHERE b.id = a.beeId AND ...

Тоді отримується інформація з інструкцією у рядку, де стовпець b.id та стовпчик a.beeId у вашому прикладі відповідають збігу. Тож у вашому прикладі вона отримає всю інформацію з таблиць a і b, де b.id дорівнює a.beeId. У моєму прикладі вона отримає всю інформацію з таблиці b і лише інформацію з стовпця a.beeName, коли b.id дорівнює a.beeId. Зауважте, що існує також пункт І, це допоможе уточнити результати.

Для деяких простих навчальних посібників та пояснень щодо приєднання до MySQL та лівих приєднань ознайомтесь із підручниками mySQL Tizag. Ви також можете ознайомитись на веб-сайті Кіта Дж. Брауна, щоб отримати додаткові відомості про приєднання.

Я сподіваюся, що це вам допоможе


Буває, що я вже все це знаю. Я фактично шукав типи приєднань, які існують. Вибачте, що мені було не ясно про те, що я знаю. Але я не шукав довгої документації лише для того, щоб отримати короткий підсумок.
Брайан Філд

Ще одна посилання у відповіді ... може бути більше того, що ви хочете, товариш.
Райан

+1 для цього редагування. Я не упереджений щодо W3Schools, як, здається, деякі люди. Можливо, я погано не бачив поганих сторін або, можливо, це просто "свята війна". Крім того, я редагував вміст із W3Schools, сподіваюся, ви не заперечуєте, але не соромтесь робити будь-які зміни, які вам подобаються. Усі ці візуальні зображення у прийнятій відповіді є приємними, але деякі насправді є варіантами того самого приєднання. Це хороша альтернатива.
Брайан Філд

Дякую Джордж, я зовсім не проти, якщо редагування є правильним! Я переконаний, що людям потрібно знайти підходящі для них джерела, більш-менш інформацію, багато прикладів чи жодне. У W3School є точні та стислі, вони, як правило, мають і хороші приклади, Tizag схожий. Легко товариш
Райан

1
В mysql немає ПОВНОГО ПРИЄДНАННЯ, тому ці посилання не дуже корисні.
Ефір

13

У мене є 2 таких таблиці:

> SELECT * FROM table_a;
+------+------+
| id   | name |
+------+------+
|    1 | row1 |
|    2 | row2 |
+------+------+

> SELECT * FROM table_b;
+------+------+------+
| id   | name | aid  |
+------+------+------+
|    3 | row3 |    1 |
|    4 | row4 |    1 |
|    5 | row5 | NULL |
+------+------+------+

INNER JOIN дбає про обидві таблиці

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

> SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
+------+------+------+------+------+

INNER JOIN не має ніякої різниці, якщо ви скасовуєте замовлення, оскільки він піклується про обидві таблиці:

> SELECT * FROM table_b b INNER JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
+------+------+------+------+------+

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

Лівий приєднується лише до першої таблиці

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

> SELECT * FROM table_a a LEFT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
|    2 | row2 | NULL | NULL | NULL |
+------+------+------+------+------+

Вище видно всі рядки table_a, хоча деякі з них не збігаються ні з чим у таблиці b, але не всі рядки table_b - лише ті, що відповідають чомусь у table_a.

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

> SELECT * FROM table_b b LEFT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
|    5 | row5 | NULL | NULL | NULL |
+------+------+------+------+------+

Тепер ми отримуємо всі рядки table_b, але лише відповідні рядки table_a.

ПРАВО ПРИЄДНАЙТЕ лише про другу таблицю

a RIGHT JOIN bотримує вам точно такі ж ряди, як і b LEFT JOIN a. Єдина відмінність - це порядок стовпців за замовчуванням.

> SELECT * FROM table_a a RIGHT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
| NULL | NULL |    5 | row5 | NULL |
+------+------+------+------+------+

Це ті самі рядки table_b LEFT JOIN table_a, що і ми бачили в розділі «ВЛІТНЕ ПРИЄДНАННЯ».

Аналогічно:

> SELECT * FROM table_b b RIGHT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
| NULL | NULL | NULL |    2 | row2 |
+------+------+------+------+------+

Чи такі самі ряди, як і table_a LEFT JOIN table_b.

Жодне приєднання не дає копій усього

Застереження "Приєднатись": Якщо ви пишете свої таблиці взагалі без пункту JOIN, просто розділених комами, ви отримуєте кожен рядок першої таблиці, що пишеться поруч із кожним рядком другої таблиці, у будь-якій можливій комбінації:

> SELECT * FROM table_b, table_a;        
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    3 | row3 | 1    |    2 | row2 |
|    4 | row4 | 1    |    1 | row1 |
|    4 | row4 | 1    |    2 | row2 |
|    5 | row5 | NULL |    1 | row1 |
|    5 | row5 | NULL |    2 | row2 |
+------+------+------+------+------+

(Це з моєї публікації в блозі Приклади типів приєднання SQL )


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

@philipxy Гаразд. Помітив це. Поки я намагався зрозуміти пояснення, я побачив такий друкарський помилок, і тому відредагував його, щоб зробити його більш зрозумілим. Дійсно, це хороша відповідь, і мій намір полягав у тому, щоб зробити це правильніше.
Ану

@Anu Ця відповідь має ті ж фрагментовані неповні описи, що й у більшості відповідей. Насправді це не говорить про те, який вихід є функцією входів. Дивіться також майже кожну відповідь на запропонований дублікат та мої коментарі на обох сторінках. Дивіться також мою відповідь там. PS Я коінциентально щойно побачив це з вчорашнього перегляду розміру редагування (Звичайно, є ще багато пов’язаних публікацій на Meta Stack Overflow & Meta Stack Exchange .)
philipxy

11

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.