何时或为何使用右外连接而不是左外连接?

时间:2009-01-12 17:59:25

标签: sql database right-join

Wikipedia州:

“在实践中,很少使用明确的右外连接,因为它们总是可以用左外连接替换,并且不提供额外的功能。”

任何人都可以提供他们更喜欢使用正确表示法的情况,为什么? 我想不出使用它的理由。对我来说,它不会让事情变得更清楚。

编辑: 我是甲骨文的老将,制定了新年的决议,让我自己摆脱(+)语法。我想做得对

11 个答案:

答案 0 :(得分:33)

我能想到使用RIGHT OUTER JOIN的唯一原因是尝试让你的SQL更加自我记录。

对于在一对多关系的从属(很多)方面具有空行的查询以及在独立方生成空行的那些查询上的右连接,您可能希望使用左连接。

这也可能发生在生成的代码中,或者商店的编码要求指定FROM子句中表的声明顺序。

答案 1 :(得分:16)

我之前从未使用过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 ...

答案 2 :(得分:15)

B RIGHT JOIN A与A LEFT JOIN B

相同

B RIGHT JOIN A读取:B ON RIGHT,THEN JOINS A.表示A位于数据集的左侧。与A LEFT JOIN B相同

如果您将LEFT JOIN重新排列为RIGHT,则无法获得任何性能。

我能想到为什么会使用RIGHT JOIN的唯一原因是你喜欢从内到外思考的人(选择*来自细节右连接标题)。就像其他人一样喜欢小端,其他人喜欢大端,其他人喜欢自上而下的设计,有些喜欢自下而上的设计。

另一个问题是,如果您想要添加另一个表格,那么您已经有了一个非常大的查询,当重新排列查询时,只需将表格插入现有查询即可。

答案 3 :(得分:6)

我唯一想到一个正确的外部联接的时候就是我正在修复一个完整的连接,而且恰好我需要结果来包含右边表格中的所有记录。尽管我和我一样懒惰,但我可能会非常恼火,我会重新安排它以使用左连接。

Wikipedia中的这个例子显示了我的意思:

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

如果您只是将FULL替换为RIGHT,则会有新的查询,而无需交换ON子句的顺序。

答案 4 :(得分:3)

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

将[BLANK]替换为:

LEFT - 如果你想要table1中的所有记录,即使他们没有匹配table2的col(也包括带匹配的table2记录)

RIGHT - 如果你想要table2中的所有记录,即使他们没有匹配table1的col(也包括带匹配的table1记录)

FULL - 如果你想要table1和table2的所有记录

每个人都在谈论什么?他们是一样的吗?我不这么认为。

答案 5 :(得分:2)

除了正确之外,SQL语句应该尽可能容易阅读和表达简洁(因为它们代表单个原子动作,你的头脑需要完全理解它们以避免意外后果。)有时表达式更多用右外连接清楚地说明。

但总是可以转换为另一个,优化器也可以与另一个一样。

有一段时间,至少有一个主要的rdbms产品只支持LEFT OUTER JOIN。 (我相信这是MySQL。)

答案 6 :(得分:2)

我使用右连接的唯一一次是当我想查看两组数据时,我已经从先前编写的查询中按照特定顺序连接左连接或内连接。在这种情况下,假设您希望将未包含在表a中的记录视为一组数据但在表b中和另一组中将记录视为不在表b中但在表a中的记录。即便如此,我倾向于这样做以节省研究时间,但如果代码可以运行多次,我会改变它。

答案 7 :(得分:2)

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

你怎么能快速/轻松地连接前两个表并加入table_c,同时确保table_c中的所有行总是被选中?

答案 8 :(得分:2)

我并没有真正考虑过正确的连接,但我认为我在近20年的时间里没有编写SQL查询,因此在使用它时遇到了合理的理由。我肯定已经看到了很多我猜测它们来自于开发人员使用内置查询构建器的地方。

每当我遇到一个,我都会重写查询以消除它 - 我发现如果你有一段时间没有访问查询,他们只需要太多额外的精力来学习或重新学习查询的意图丢失或返回不正确的结果并不少见 - 而且通常这种不正确性导致我要求查看查询无法正常工作的原因。

在考虑它时,一旦你引入了一个右连接,你现在就拥有了我认为需要在中间遇到的逻辑分支。如果引入了其他要求/条件,这两个分支可能会进一步扩展,您现在需要更加复杂,以确保一个分支不会导致错误的结果。

此外,一旦您引入了正确的联接,其他经验不足的开发人员稍后可能会将其他表格固定到查询的右连接部分,并且这样做会扩展仍然需要的竞争逻辑流程在中间见面;或者在某些情况下,我已经看到,开始嵌套视图,因为他们不想触及原始逻辑,也许部分,这是因为他们可能无法理解驱动逻辑的查询或业务规则。

答案 9 :(得分:1)

在某些SQL数据库中,有优化器提示,告诉优化器按照它们在FROM子句中出现的顺序加入表 - 例如Oracle中的/*+ORDERED */。在一些简单的实现中,这甚至可能是唯一可用的执行计划。

在这种情况下,FROM子句中的表顺序很重要,因此RIGHT JOIN可能很有用。

答案 10 :(得分:0)

如果你没有在这种情况下加入,我认为这很难。与甲骨文有关。

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