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изменений.

Я уже знаю, как работают объединения, я просто хочу знать, существуют ли другие типы объединений или это просто разные способы получить тот же результат.


Отвечает ли это на ваш вопрос? В чем разница между "INNER JOIN" и "OUTER JOIN"?
Филипп

Ответы:


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:
Руфинус

1
Я поражен, печатая эти диаграммы и помещая их на мою офисную стену. Вы изменили мою жизнь!
Йоссико

41
Вопрос именно о MySQL. MySQL не поддерживает соединения FULL OUTER.
Майк Баранчак

4
и, конечно, это должно быть причиной, чтобы не публиковать эту статью. вздох
Руфинус

27

Исходя из вашего комментария, простые определения каждого лучше всего найти в W3Schools . Первая строка каждого типа дает краткое объяснение типа соединения.

  • JOIN: возвращать строки, если в обеих таблицах есть хотя бы одно совпадение
  • LEFT JOIN: вернуть все строки из левой таблицы, даже если в правой таблице нет совпадений
  • RIGHT JOIN: вернуть все строки из правой таблицы, даже если в левой таблице нет совпадений
  • FULL JOIN: возвращать строки, если в одной из таблиц есть совпадение

КОНЕЦ РЕДАКТИРОВАНИЯ

В двух словах, разделенный запятыми пример

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. Обратите внимание, что есть также предложение AND, это поможет уточнить ваши результаты.

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

Я надеюсь, это поможет вам


Бывает, что я все это уже знаю. Я на самом деле искал типы соединений, которые есть. Извините, я не понял, что я знаю. Но я не искал длинную документацию, чтобы получить краткое резюме.
Брайан Филд

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

+1 за это редактирование. Я не склонен против W3Schools, как некоторые люди, кажется. Возможно, я не слишком много видел дурных сторон или, может быть, это просто «священная война». Кроме того, я редактировал материалы W3Schools, надеюсь, вы не возражаете, но не стесняйтесь вносить любые изменения, которые вам нравятся. Все эти визуальные эффекты в принятом ответе хороши, но некоторые на самом деле являются вариациями одного и того же соединения. Это хорошая альтернатива.
Брайан Филд

Спасибо Джордж, я не против, если редактирование правильное! Я верю, что людям нужно найти источники, которые им подходят, больше или меньше информации, много примеров или их нет. Школы W3 точны и лаконичны, у них тоже есть хорошие примеры, Тизаг похож. Полегче, приятель
Райан

1
в MySQL нет FULL JOIN, поэтому эти ссылки не очень полезны.
эфир

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 заботится только о первом столе

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.

RIGHT JOIN заботится только о втором столе

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, что и мы видели в разделе LEFT JOIN.

Так же:

> 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: если вы пишете свои таблицы вообще без предложения 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 )


@ Ану Пожалуйста, не делайте таких тривиальных правок, когда ваша низкая репутация означает, что ваши правки должны быть просмотрены другими, вы просто тратите их время. Это редактирование должно быть отклонено, так как нет разницы. Код, который вы изменили, на самом деле не был неправильным, и вы могли бы прокомментировать.
Филипп

@philipxy Хорошо. Отмечено с этим. Пока я пытался понять объяснение, я увидел такую ​​опечатку, и поэтому отредактировал, чтобы сделать ее более понятной. Действительно, это хороший ответ, и я намеревался сделать его более правильным.
Ану

@Anu Этот ответ имеет те же фрагментированные неполные описания, что и в большинстве ответов. Это на самом деле не говорит, что выход в зависимости от входных данных. Смотрите также почти каждый ответ в предложенном дубликате и мои комментарии на обеих страницах. Смотрите также мой ответ там. PS По совпадению я только что видел это из вчерашнего пересмотренного размера редактирования (Конечно, на Meta Stack Overflow & Meta Stack Exchange есть еще много
похожих сообщений

11

Полное внешнее соединение не существует в MySQL, вам может понадобиться комбинация левого и правого соединения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.