Причина, по которой предпочитаю RIGHT JOIN, а не LEFT JOIN


18

Если я правильно понимаю, каждый RIGHT JOIN:

SELECT Persons.*, Orders.*
FROM Orders
RIGHT JOIN Persons ON Orders.PersonID = Persons.ID

можно выразить как LEFT JOIN:

SELECT Persons.*, Orders.*
FROM Persons
LEFT JOIN Orders ON Persons.ID = Orders.PersonID

Мое личное мнение таково, что в заявлении говорится:

  • Сначала получите Persons
  • Затем разверните / повторите по Personsмере необходимости, чтобы соответствоватьOrders

лучше выражается в порядке, Persons LEFT JOIN Ordersчем в обратном порядке Orders RIGHT JOIN Persons(и я никогда не использую RIGHT JOINв результате).

Есть ли ситуации, когда RIGHT JOINпредпочтение отдается? Или есть ли случаи, когда RIGHT JOINможно сделать что-то, что LEFT JOINне может?


12
Я не могу вспомнить ни одного случая, когда я хотел правильно присоединиться. У меня были случаи, когда план выполнения запроса переключал левое соединение в правое соединение по соображениям производительности. Но с точки зрения написания чистого кода, нет, я не помню, чтобы когда-либо писал правильное соединение.
Брэндон

2
Я не рассматриваю это как вопрос о «объяснении, написании или отладке кода». Спрашивается, почему у языка есть две особенности, которые, по-видимому, делают одно и то же, если между ними есть какая-то разница, и если нет, то когда предпочтительнее «неочевидная».
Филипп Кендалл

1
Нет, левое соединение почти всегда отражает то, что вам нужно наиболее кратко, и его легче рассуждать. На моем рабочем месте у нас фактически есть стандарт для предотвращения правых объединений, поскольку никогда не бывает случаев, когда они необходимы (то есть они всегда могут быть заменены противоположным левым соединением).
mgw854

8
Я сбросил количество голосов при закрытии - здесь этот вопрос является актуальным, поскольку понимание различия между объединениями влияет на разработку программного обеспечения (проектирование базы данных является частью проектирования программного обеспечения, как и алгоритмы, которые могут запрашивать базы данных). Это также может быть по теме у администраторов баз данных , и там также может быть дубликат.
Томас Оуэнс

1
Я не уверен, если вы предлагаете, что RIGHT JOINрекомендуется или более распространенным. Если это ваша предпосылка, это неправильно. Я не могу вспомнить время, когда я видел правильное соединение, использованное ни в коде, ни в примерах. Это JOINили LEFT OUTER JOIN. В редких случаях вы можете увидеть FULL OUTER JOIN.
JimmyJames

Ответы:


12

Это зависит от того, какое требование вы пытаетесь выполнить.

Это не то же самое, что сказать: «дай мне всех людей и их соответствующие заказы», что «я хочу, чтобы все заказы с их соответствующими лицами» , особенно если вы собираетесь использовать, is nullчтобы привести строки без соответствующего соответствия. Это то, что я называю «доминантной таблицей», то есть таблицей, из которой я хочу получать строки, независимо от того, не было ли соответствующей строки на другой стороне соединения.

Посмотрите на эти изображения, и вы заметите, что они не совпадают:

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

Источник изображения - это отличная статья .

Но вы правы в том, что оба требования могут быть выполнены с любым объединением, просто инвертируя порядок таблиц в объединении.

Но я предполагаю, что для западных людей, привыкших писать слева направо, более естественно использовать левое соединение вместо правого , поскольку мы видим, как будто мы хотим, чтобы соединения были в том же направлении или в том же порядке, что и selectстолбцы ed.

Таким образом, возможная причина предпочитать правое объединение состоит в том, что в вашей культуре вы пишете справа налево (как в арабской или ивритской системах письма), и вы склонны мыслить таким образом, то есть, возможно, в вашем мозгу текстовая информация течет справа налево ,

Некоторые лингвисты считают, что ваш язык влияет на ваш образ мышления: https://www.edge.org/conversation/lera_boroditsky-how-does-our-language-shape-the-way-we-think


1
Я начал думать в этом направлении, но я не думаю, что это правильно. Я начал представлять SQL на иврите (чего я никогда не делал). ОК: вправо, справа налево, сверху вниз. Сначала вы все равно упомянете таблицу A, а затем таблицу B. При правильном объединении вы исключите (особенно в нулевом случае) большинство или всю таблицу, упомянутую первой. Я думаю, что человеческий разум имеет тенденцию ассоциироваться сначала с первичным и самым важным . Это происходит независимо от направления письма. Вы могли бы назвать их "ПЕРВЫМ СОЕДИНЕНИЕМ" и "ВТОРОМ СОЕДИНЕНИЕМ", и этот уклон все еще будет происходить.
Майк поддерживает Монику

Я включил ссылку на изображение, которое вы показали ниже.
Джон Рейнор

@ Майк, я не предлагаю людям писать SQL на арабском или иврите. Просто, возможно, ориентация вашего родного языка может быть причиной для того, чтобы вы предпочли правильное соединение. Но это только возможность. Я считаю, что левые соединения более естественны.
Тулаинс Кордова

Теперь я отдала должное создателю изображения. У меня это много лет было в моем HD, и я не помнил, откуда это
взято

Я свободно говорю на иврите и все еще нахожу LEFT JOINболее естественным.
Зев Шпиц

3

Нет ничего (о чем я знаю), которое можно сделать с правым соединением, чего нельзя сделать с левым соединением. Но иногда синтаксис с левыми соединениями выглядит ужаснее. Допустим, у вас есть следующие таблицы:

Persons
ID | Name

Orders
ID | CustomerId | other unimportant stuff

SpecialOrderDetails
ID | OrderId | other stuff

Допустим, вам нужно получить список всех людей в вашей базе данных и всех заказов, которые у них есть, с особыми деталями заказа (скажем, что не все заказы имеют особые детали заказа). Таким образом, вы обычно делаете левое соединение от людей к заказам. Но тогда вы должны присоединиться в деталях специального заказа. Если вы используете там внутреннее соединение, это фактически сделает левое соединение людей от заказов во внутреннее соединение. IE: это то, что вы хотите сделать, но не работает (это исключит любого, у кого нет специального заказа):

select p.*, o.*, d.*
from Persons p
left join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

Таким образом, вы можете переписать это так:

--get all the people without a special order
select p.*, NULL, NULL, ... --NULLs placeholders for all the fields from OrderDetails and SpecialOrderDetails
from Persons p
left join Orders o on o.CustomerId = p.Id
left join SpecialOrderDetails d on d.OrderId = o.Id
where o.Id is null 

union

--get all the people with a special order
select p.*, o.*, d.*
from Persons p
inner join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

Не совсем понятно (без комментариев), но это делает работу. Если это нечто большее, чем одноразовое (то есть что-то, что кто-то собирается когда-нибудь вернуться и поддержать), использование правильного соединения может прояснить, каково было намерение.

select p.*, o.*, d.*
from Orders o
inner join SpecialOrderDetails d on d.OrderId = o.Id
right join Persons p on p.Id = o.CustomerId

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

select p.*, o.*, d.*
from Persons p
left join Orders o 
    inner join SpecialOrderDetails d on d.OrderId = o.Id
on o.CustomerId = p.Id

На данный момент, это выбор того, что наиболее ясно и что большинство людей поймет (знаете ли вы, как использовать этот синтаксис в Google, если вы не знали, что он называется вложенным объединением?).

Короче говоря, вам не нужны правильные объединения, но они могут облегчить чтение.


Я думаю, может быть, вы просто правша.
Роберт Харви

Я не понимаю , почему вы не можете писать множественным левой присоединяется в данном случае: SELECT p.*, o.*, d.* FROM Persons p LEFT JOIN Orders o ON o.CustomerID = p.ID LEFT JOIN SpecialOrders d ON o.Id = d.OrderID.
Зев Шпиц

@RobertHarvey Я, но я не уверен, какое отношение к этому имеет рука об руку.
Becuzz

@ZevSpitz Возможно, из того, что я написал, было неясно, но идея была в том, что вы хотели, чтобы поля были только из заказов, только если существует специальная запись подробностей заказа, т.е. осталось присоединиться к ним, только если пара из них существует.
Becuzz

-1

Я мог видеть, что ПРАВОЕ СОЕДИНЕНИЕ используется для целей репликации / слияния. Допустим, у меня есть две таблицы A и B. A слева и B справа. Допустим, я хотел реплицировать данные между этими двумя таблицами, чтобы сделать их эквивалентными.

Если бы я хотел показать все данные, которые были в A, но не в B, это было бы ЛЕВОЕ соединение. Если бы я хотел показать все данные в B, которых не было в A, он бы УЖЕ присоединился.

Таким образом, иногда LEFT и RIGHT оказываются полезными при объединении и репликации данных, чтобы держать вещи в перспективе.

Кроме этого, я не вижу другой причины использовать соединение RIGHT, поскольку все соединения RIGHT могут быть преобразованы в соединения LEFT или наоборот, все соединения LEFT могут быть преобразованы в соединения RIGHT в зависимости от того, как таблицы упорядочены или визуализированы. Таким образом, это было бы вопросом предпочтения в других случаях.

Вот хорошая ссылка для визуализации соединений SQL.

http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins


-1

левое соединение не является противоположностью правому соединению, проверьте следующий случай, который дает разные результаты

select * from 
(select 1 as x  where 1=1) a left join 
(select 1 as x  where 1=0) b on a.x=b.x inner join 
(select 1 as x  where 1=1) c on b.x=c.x

select * from 
(select 1 as x where 1=1) c inner join 
(select 1 as x where 1=0) b on c.x=b.x right join 
(select 1 as x where 1=1) a on b.x=a.x

таблицы b anc c всегда внутренне соединены, но в первом a слева соединены с остальными, а во втором a соединены справа

левое соединение не возвращает строк, тогда как правое соединение возвращает строки


это читает больше как тангенциальной комментарий см Как ответить
комар

-2

Там никогда нет никаких причин, чтобы предпочесть RIGHT JOIN, и LEFT JOINгораздо яснее:

ВЫБЕРИТЕ Persons. *, Orders. * ОТ Persons ЛЕВОЕ СОЕДИНЕНИЕ Приказов ON Persons.ID = Orders.PersonID

поскольку это позволяет вам сразу увидеть, какая таблица запрашивается. Тогда как с RIGHT JOIN:

ВЫБЕРИТЕ Persons. *, Orders. * ИЗ ПРИЛОЖЕНИЙ ПРАВО ПРИСОЕДИНЯЕТСЯ Persons ON Orders.PersonID = Persons.ID

первая таблица написана после JOIN.

По своему опыту я никогда не видел RIGHT JOIN.


1
Что это добавляет к вопросу? Вопрос не в чем разница? ; Вопрос в том, почему я должен использовать RIGHT JOIN? ,
Зев Шпиц

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