Sql объединяется как диаграмма Венна
У меня возникли проблемы с пониманием подключений в sql и я столкнулся с этим изображением, которое, я думаю, могло бы мне помочь. Проблема в том, что я не совсем понимаю это. Например, объединение в верхнем правом углу изображения, которое окрашивает полный круг B красным цветом, но только перекрывается с A. Изображение похоже на то, что круг B является основным фокусом оператора sql, но оператор sql сам, начиная с A (выберите из A, join B), передает мне противоположное впечатление, а именно, что A будет в центре внимания оператора sql.
Аналогично, изображение ниже, которое включает только данные из круга B, поэтому почему A включен вообще в заявлении о соединении?
Вопрос: Работая по часовой стрелке сверху справа и заканчивая в центре, кто-то может предоставить дополнительную информацию о представлении каждого изображения sql, объясняя
a) почему объединение должно быть необходимо в каждом случае (например, особенно в ситуациях, когда данные, взятые из A или B, где только A или B, но не оба, окрашены)
b) и любые другие детали, которые пояснят, почему изображение является хорошим представлением sql
Ответы
Ответ 1
Я думаю, что ваша основная основная путаница заключается в том, что когда (например) только A
выделяется красным цветом, вы принимаете это как "запрос возвращает данные только из A
", но на самом деле это означает, запрос возвращает данные только для тех случаев, когда A
имеет запись ". Запрос может по-прежнему содержать данные из B. (Для случаев, когда B
не имеет записи, запрос заменит NULL
.)
Аналогично, изображение ниже, которое включает только данные из круга B, поэтому почему A включен вообще в заявлении о соединении?
Если вы имеете в виду — изображение A
целиком находится в белом цвете, и там есть красная полумесячная фигура для части B
, которая не перекрывается с A
, а затем: причина, по которой A
появляется в запросе, равна A
заключается в том, как он находит записи в B
, которые необходимо исключить. (Если <<20 > не появилось в запросе, то диаграмма Венна не имела бы A
, она отображала бы только B
, и не было бы возможности отличить нужные записи от нежелательных.)
Изображение похоже на то, что круг B является основным фокусом оператора sql, но сам оператор sql, начиная с A (выберите A, соедините B), передает мне противоположное впечатление, а именно, что A будет быть в центре внимания оператора sql.
Совершенно верно. По этой причине RIGHT JOIN
являются относительно необычными; хотя запрос, который использует LEFT JOIN
, почти всегда может быть переназначен вместо RIGHT JOIN
(и наоборот), обычно люди будут писать свои запросы с помощью LEFT JOIN
, а не с помощью RIGHT JOIN
.
Ответ 2
Я согласен с Кейдом в отношении ограничений диаграмм Венна. Более привлекательным визуальным представлением может быть это.
Таблицы
SELECT A.Colour, B.Colour FROM A CROSS JOIN B SQL Fiddle
Перекрестное объединение (или декартово произведение) дает результат с каждой комбинацией строк из двух таблиц. Каждая таблица имеет 4 строки, поэтому в результате получается 16 строк.
SELECT A.Colour, B.Colour FROM IN INER JOIN B ON A.Colour = B.Colour SQL Fiddle
Внутреннее соединение логически возвращает все строки из перекрестного соединения, которые соответствуют условию объединения. В этом случае пять делают.
SELECT A.Colour, B.Colour FROM IN INER JOIN B ON A.Colour NOT IN ( "Зеленый", "Синий" ) SQL Fiddle
Внутреннее условие соединения необязательно должно быть условием равенства, и ему не нужно ссылаться на столбцы из (или даже любой) таблиц. Вычисление A.Colour NOT IN ('Green','Blue')
в каждой строке перекрестного соединения возвращает.
Внутреннее условие объединения 1=1
будет оцениваться как true для каждой строки в перекрестном объединении, поэтому два эквивалентны (SQL Fiddle).
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour SQL Fiddle
Внешние соединения логически оцениваются так же, как и внутренние соединения, за исключением того, что если строка из левой таблицы (для левого соединения) не объединяется ни с одной строкой из правой таблицы, она сохраняется в результате с помощью NULL
для правых столбцов.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL SQL Fiddle
Это просто ограничивает предыдущий результат только возвратом строк, где B.Colour IS NULL
. В этом конкретном случае это будут строки, которые были сохранены, поскольку они не совпадали в правой таблице, и запрос возвращает единственную красную строку, не сопоставленную в таблице B
. Это называется ant semi-join.
Важно выбрать столбец для теста IS NULL
, который либо не имеет значения NULL, либо для которого условие соединения гарантирует, что любые значения NULL
будут исключены для правильной работы этого шаблона и избежания просто возврата строки, которые имеют значение NULL
для этого столбца в дополнение к несогласованным строкам.
SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour SQL Fiddle
Прямые внешние соединения действуют аналогично левым внешним соединениям, за исключением того, что они сохраняют несоответствующие строки из правой таблицы, а null расширяют левые столбцы.
SELECT A.Colour, B.Colour FROM FULL OUTER JOIN B ON A.Colour = B.Colour SQL Fiddle
Полное внешнее объединение объединяет поведение левого и правого соединений и сохраняет несоответствующие строки как из левой, так и из правой таблиц.
Ответ 3
Диаграммы Венна подходят для представления заданных операций, таких как UNION, INTERSECTS, EXCEPT и т.д.
В той степени, в которой моделированные операции, такие как EXCEPT, моделируются такими вещами, как LEFT JOIN WHERE. rhs.KEY NULL, эта диаграмма является точной.
В противном случае это вводит в заблуждение. Например, любое соединение может привести к умножению строк, если критерии соединения не равны 1:1. Но наборам разрешено содержать только отдельные элементы, поэтому они не могут быть представлены в виде заданных операций.
Тогда есть КРОСС-ПРИСОЕДИНЕНИЕ или ВХОДНОЕ СОЕДИНЕНИЕ 1 = 1 - это не похоже на INNER JOIN, как показано на этой диаграмме, и не может быть создан набор, который будет действительно описан диаграммой Венна. Не говоря уже обо всех других возможных треугольных объединениях, я и анти-объединениях:
lhs INNER JOIN rhs ON rhs.VALUE < lhs.VALUE (triangular)
или
SELF self1
INNER JOIN SELF self2
ON self2.key <> self1.key
AND self1.type = self2.type
(self cross and anti-join, чтобы найти все похожие члены семейства, кроме себя - self1 и self2, являются одним и тем же множеством, а результат - правильным подмножеством)
Прикрепление к соединениям на клавишах может быть прекрасным в течение первых нескольких минут учебника, но это может привести к плохому пути для изучения того, что происходит. Я думаю, что это то, что вы нашли.
Эта идея, которую Venn Diagrams может представлять JOINs, как правило, должна уйти.
Ответ 4
Когда вы выполните соединение, вполне вероятно, что ваши две таблицы могут не совпадать. В частности, в могут быть некоторые строки, которые не соответствуют ни одному в B, или дублируют строки в A, которые совпадают с одной строкой в B, и наоборот.
Когда это произойдет, у вас есть выбор:
- для каждого A возьмем один B, который работает, если он есть. (верхний левый)
- возьмите каждую пару, которая полностью соответствует (отбросьте любые, которые отсутствуют либо A, либо B-центр)
- для каждого B, возьмите один A, который работает, если он есть (верхний правый)
- возьмите ВСЕ (внизу слева)
Центр слева и справа технически соединяется, но бессмысленны; они могли бы быть более эффективно написаны SELECT <select_list> FROM TableA A WHERE A.Key NOT IN (SELECT B.Key FROM TableB B)
(или наоборот).
В прямом ответе на ваше замешательство, RIGHT JOIN
говорит: "следующее выражение является фокусом этого запроса".
Внизу справа довольно странно, и я не вижу причин, по которым вам это нужно. Он возвращает результаты из двух внешних средних запросов, смешанных вместе с NULL
во всех столбцах для противоположной таблицы.
Ответ 5
Для правильного соединения да, синтаксис может ввести в заблуждение, но да, это то, что кажется. Когда вы говорите "TableA RIGHT JOIN TableB", это действительно говорит о том, что TableB является основной таблицей, на которую вы ссылаетесь, и TableA просто висит там, где она имеет соответствующие записи. Это читает странно в запросах, потому что TableA указан первым, поэтому ваш мозг автоматически назначает ему больше приоритета, даже несмотря на то, что TableB действительно является более важной таблицей в запросе. По этой причине вы редко видите правые соединения в реальном коде.
Итак, вместо A и B давайте возьмем две вещи, которые легко отслеживать. Предположим, у нас есть две таблицы для информации людей, ShoeSize и IQ. У вас есть информация о ShoeSize для некоторых людей, некоторые данные IQ для некоторых людей. И иметь PersonID на обеих таблицах, к которым вы можете присоединиться.
По часовой стрелке сверху справа (даже если это начинается с некоторых более сложных и надуманных случаев):
- ShoeSize RIGHT JOIN IQ → предоставить мне всю информацию IQ. Включите любую информацию ShoeSize для тех людей, если у нас есть.
- ShoeSize RIGHT JOIN IQ WHERE ShowSize.PersonID = NULL → Дайте мне всю информацию IQ, но только для людей, у которых нет информации о размере обуви.
- ShoeSize FULL OUTER JOIN IQ WHERE ShoeSize.PersonID = NULL AND IQ.PersonID = NULL → Дайте мне информацию о размере обуви только для людей, у которых нет информации IQ, плюс информация IQ для людей, которые не имеют информация о размере обуви
- ShoeSize FULL OUTER JOIN IQ → Дайте мне все, все размеры обуви и все данные IQ. Если какие-либо записи ShoeSizes и IQ имеют один и тот же идентификатор Personid, включите их в одну строку.
- ShoeSize LEFT JOIN IQ WHERE IQ.PersonID = NULL → Дайте мне всю информацию о размере обуви, но только для людей, у которых нет информации IQ.
- ShoeSize LEFT JOIN IQ → Дайте мне всю информацию о размере обуви. Включите любую информацию IQ для тех людей, если у нас есть.