Когда или почему вы бы использовали правое внешнее соединение вместо левого? - PullRequest
49 голосов
/ 12 января 2009

Википедия говорится:

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

Может ли кто-нибудь представить ситуацию, когда он предпочел использовать ПРАВИЛЬНОЕ обозначение и почему? Я не могу придумать причину, чтобы когда-либо использовать это. Для меня это никогда не прояснит ситуацию.

Edit: Я ветеран Oracle, делающий новогоднюю резолюцию, чтобы отучить себя от (+) синтаксиса. Я хочу сделать это правильно

Ответы [ 11 ]

33 голосов
/ 12 января 2009

Единственная причина, по которой я могу использовать RIGHT OUTER JOIN, - попытаться сделать ваш SQL более самодокументированным.

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

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

16 голосов
/ 20 февраля 2015

Я никогда раньше не использовал right join и никогда не думал, что мне это действительно может понадобиться, и это кажется немного неестественным. Но после того, как я подумал об этом, это может быть очень полезно в ситуации, когда вам нужно внешнее соединение одной таблицы с пересечением многих таблиц, поэтому у вас есть такие таблицы:

enter image description here

И хочу получить такой результат:

enter image description here

Или в SQL (MS SQL Server):

declare @temp_a table (id int)
declare @temp_b table (id int)
declare @temp_c table (id int)
declare @temp_d table (id int)

insert into @temp_a
select 1 union all
select 2 union all
select 3 union all
select 4

insert into @temp_b
select 2 union all
select 3 union all
select 5

insert into @temp_c
select 1 union all
select 2 union all
select 4

insert into @temp_d
select id from @temp_a
union
select id from @temp_b
union
select id from @temp_c

select *
from @temp_a as a
    inner join @temp_b as b on b.id = a.id
    inner join @temp_c as c on c.id = a.id
    right outer join @temp_d as d on d.id = a.id

id          id          id          id
----------- ----------- ----------- -----------
NULL        NULL        NULL        1
2           2           2           2
NULL        NULL        NULL        3
NULL        NULL        NULL        4
NULL        NULL        NULL        5

Так что если вы переключитесь на left join, результаты не будут такими же.

select *
from @temp_d as d
    left outer join @temp_a as a on a.id = d.id
    left outer join @temp_b as b on b.id = d.id
    left outer join @temp_c as c on c.id = d.id

id          id          id          id
----------- ----------- ----------- -----------
1           1           NULL        1
2           2           2           2
3           3           3           NULL
4           4           NULL        4
5           NULL        5           NULL

Единственный способ сделать это без правильного объединения - использовать общее табличное выражение или подзапрос

select *
from @temp_d as d
    left outer join (
        select *
        from @temp_a as a
            inner join @temp_b as b on b.id = a.id
            inner join @temp_c as c on c.id = a.id
    ) as q on ...
15 голосов
/ 12 января 2009

B RIGHT JOIN A - то же самое, что A LEFT JOIN B

B RIGHT JOIN A гласит A: B ON RIGHT, THEN JOINS A. означает, что A находится слева от набора данных. точно так же, как левое соединение B

Невозможно добиться производительности, если вы переставите ЛЕВЫЕ СОЕДИНЕНИЯ в ПРАВО.

Единственная причина, по которой я могу подумать, почему можно использовать RIGHT JOIN, - это если вы тот человек, который любит думать изнутри (выберите * из подробного заголовка правого соединения). Это как другие, как little-endian, другие как big-endian, другие как дизайн сверху вниз, другие как дизайн снизу вверх.

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

6 голосов
/ 12 января 2009

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

Этот пример из Википедии показывает, что я имею в виду:

SELECT *  
FROM   employee 
   FULL OUTER JOIN department 
      ON employee.DepartmentID = department.DepartmentID

Если вы просто замените слово FULL на RIGHT, у вас будет новый запрос без необходимости менять порядок предложения ON.

3 голосов
/ 12 января 2009
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col

Заменить [ПУСТО] на:

ВЛЕВО - если вы хотите, чтобы все записи из таблицы1, даже если они не имеют col, совпадающего с таблицей2 (также включены записи таблицы2 с совпадениями)

ВПРАВО - если вы хотите, чтобы все записи из таблицы2, даже если у них нет столбца, который соответствует таблице1 (также включены записи из таблицы1 с совпадениями)

FULL - если вам нужны все записи из таблицы1 и из таблицы2

О чем все говорят? Они одинаковые? Я так не думаю.

2 голосов
/ 10 декабря 2016

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

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

Размышляя об этом, после того, как вы введете правое соединение, у вас теперь есть то, что я бы посчитал конкурирующими ветвями логики, которые нужно встретить посередине. Если будут введены дополнительные требования / условия, обе эти ветви могут быть дополнительно расширены, и теперь вам придется усложнять работу, чтобы убедиться, что одна ветвь не приводит к неверным результатам.

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

2 голосов
/ 07 октября 2012
SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....

Как еще можно быстро / легко объединить первые 2 таблицы и объединить их с table_c, при этом всегда выбирая все строки в table_c?

2 голосов
/ 13 января 2009

Единственный раз, когда я использовал правильное соединение, было, когда я хочу просмотреть два набора данных, и у меня уже есть соединения в определенном порядке для левого или внутреннего соединения из ранее написанного запроса. В этом случае, скажем, вы хотите видеть как один набор данных записи, не включенные в таблицу a, но в таблицу b, а в другой набор записей не в таблицу b, а в таблицу a. Даже тогда я склонен делать это только для того, чтобы сэкономить время на исследованиях, но изменил бы его, если бы это был код, который запускался бы более одного раза.

2 голосов
/ 12 января 2009

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

Но одно всегда можно преобразовать в другое, и оптимизатор будет работать так же хорошо, как и один.

В течение достаточно долгого времени, по крайней мере, один из основных продуктов rdbms поддерживал только LEFT OUTER JOIN. (Я считаю, что это был MySQL.)

1 голос
/ 17 января 2017

В некоторых базах данных SQL существуют подсказки оптимизатора, которые сообщают оптимизатору о присоединении таблиц в том порядке, в котором они указаны в предложении FROM - например, /*+ORDERED */ в Oracle. В некоторых простых реализациях это может быть даже единственный доступный план выполнения.

В таких случаях порядок таблиц в предложении FROM имеет значение, поэтому RIGHT JOIN может быть полезным.

...