Подтвердить что ты не робот

Когда или почему вы используете правое внешнее соединение вместо левого?

Wikipedia:

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Я никогда раньше не использовал 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 ...

Ответ 3

B ПРАВОЕ СОЕДИНЕНИЕ A такое же, как A LEFT JOIN B

B ПРАВИЛЬНОЕ СОЕДИНЕНИЕ A: B ON RIGHT, THEN JOINS A. означает, что A находится в левой части набора данных. точно так же, как A LEFT JOIN B

Нет производительности, которую можно получить, если вы измените LEFT JOINs на правое.

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

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

Ответ 4

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

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

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

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

Ответ 5

SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col

Замените [BLANK] на:

LEFT - если вы хотите, чтобы все записи из таблицы1, даже если у них нет col, который соответствует таблице2 (также включены записи таблицы2 со спичками)

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

FULL - если вы хотите, чтобы все записи из таблицы 1 и таблицы2

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

Ответ 6

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

Но всегда можно преобразовать в другое, и оптимизатор будет делать то же самое, что и другой.

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

Ответ 7

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

Ответ 8

SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....

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

Ответ 9

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

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

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

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

Ответ 10

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

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

Ответ 11

Мне кажется, что это сложно, если вы не имеете права присоединиться к этому делу. ex с оракулом.

with a as(
     select 1 id, 'a' name from dual union all
     select 2 id, 'b' name from dual union all
     select 3 id, 'c' name from dual union all
     select 4 id, 'd' name from dual union all
     select 5 id, 'e' name from dual union all
     select 6 id, 'f' name from dual 
), bx as(
   select 1 id, 'fa' f from dual union all
   select 3 id, 'fb' f from dual union all
   select 6 id, 'f' f from dual union all
   select 6 id, 'fc' f from dual 
)
select a.*, b.f, x.f
from a left join bx b on a.id = b.id
right join bx x on a.id = x.id
order by a.id

Ответ 12

Create table Department
(
    Id int primary key,
    DepartmentName nvarchar(50)
)
Go

Insert into Department values (1, 'IT')
Insert into Department values (2, 'HR')
Insert into Department values (3, 'Payroll')
Insert into Department values (4, 'Administration')
Insert into Department values (5, 'Sales')
Go

Create table Employee
(
    Id int primary key,
    Name nvarchar(50),
    Gender nvarchar(10),
    Salary int,
    DepartmentId int foreign key references Department(Id)
)
Go

Insert into Employee values (1, 'Mark', 'Male', 50000, 1)
Insert into Employee values (2, 'Mary', 'Female', 60000, 3)
Insert into Employee values (3, 'Steve', 'Male', 45000, 2)
Insert into Employee values (4, 'John', 'Male', 56000, 1)
Insert into Employee values (5, 'Sara', 'Female', 39000, 2)
Go

The Following two Query gives the same result

Select D.DepartmentName, E.Name, E.Gender, E.Salary
from Department D
Left Join Employee E
On D.Id = E.DepartmentId

Select D.DepartmentName, E.Name, E.Gender, E.Salary
from Employee E 
right Join Department D
On D
--------------------------
IT    Mark   Male    50000
IT    John   Male    56000
HR    Steve  Male    45000
HR    Sara   Female  39000
Pay   Mary   Female  60000
Admin NULL   NULL    NULL
Sales NULL   NULL    NULL

Таким образом, чтобы завершить, "левое соединение B" дает тот же результат, что и "B правое соединение A", а "B левое соединение A" дает тот же результат, что и "правое соединение B"