73

维基百科指出:

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

谁能提供他们更喜欢使用 RIGHT 表示法的情况,为什么?我想不出使用它的理由。对我来说,它永远不会让事情变得更清楚。

编辑:我是一名 Oracle 资深人士,我制定了新年决议,让自己摆脱 (+) 语法。我想做对

4

11 回答 11

44

我能想到使用 RIGHT OUTER JOIN 的唯一原因是尝试使您的 SQL 更具自我记录性。

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

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

于 2009-01-12T18:08:04.163 回答
24

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 的唯一原因是,如果您是那种喜欢从内而外思考的人(从详细信息右连接标题中选择 *)。就像其他人喜欢little-endian,其他人喜欢big-endian,其他人喜欢自上而下设计,其他人喜欢自下而上设计。

另一种情况是,如果您已经有一个庞大的查询,您想在其中添加另一个表,而重新排列查询很麻烦,那么只需使用 RIGHT JOIN 将表插入现有查询。

于 2009-01-12T18:25:29.980 回答
23

我以前从未使用right join过,也从未想过我真的需要它,而且看起来有点不自然。但是在我考虑之后,它在这种情况下真的很有用,当你需要外连接一个表和许多表的交集时,你有这样的表:

在此处输入图像描述

并希望得到这样的结果:

在此处输入图像描述

或者,在 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 ...
于 2015-02-20T14:26:50.837 回答
10

唯一一次我会想到右外连接是在修复全连接时,碰巧我需要结果包含右侧表中的所有记录。不过,即使我很懒惰,我也可能会非常恼火,以至于我会重新排列它以使用左连接。

这个来自维基百科的例子说明了我的意思:

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

如果您只是将单词替换为FULLRIGHT有一个新查询,则无需交换ON子句的顺序。

于 2009-01-12T18:09:20.497 回答
3
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col

将 [空白] 替换为:

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

右 - 如果您想要 table2 中的所有记录,即使它们没有与 table1 匹配的 col(也包括匹配的 table1 记录)

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

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

于 2009-01-12T18:25:39.120 回答
3
SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....

在确保始终选择 table_c 中的所有行的同时,您还能如何快速/轻松地内部连接前 2 个表并与 table_c 连接?

于 2012-10-07T15:10:06.653 回答
3

我真的不必对正确的连接考虑太多,但我想我在近 20 年的编写 SQL 查询中还没有遇到过使用它的合理理由。我当然已经看到了很多我猜想来自开发人员使用内置查询构建器的地方。

每当我遇到一个,我都会重写查询以消除它 - 我发现如果你有一段时间没有访问过查询并且它没有访问,他们只是需要太多额外的精神能量来学习或重新学习查询的意图丢失或返回不正确的结果并不常见——通常正是这种不正确导致我要求检查查询为什么不起作用。

在考虑它时,一旦你引入了右连接,你现在就有了我认为需要在中间相遇的竞争逻辑分支。如果引入了额外的要求/条件,这两个分支可能会进一步扩展,您现在需要处理更多复杂性,以确保一个分支不会导致不正确的结果。

此外,一旦您引入了右连接,稍后处理查询的其他经验不足的开发人员可能会简单地将附加表添加到查询的右连接部分,这样做会扩展仍然需要满足的竞争逻辑流中间; 或者在我见过的某些情况下,开始嵌套视图是因为他们不想触及原始逻辑,这可能部分是因为他们可能不理解驱动逻辑的查询或业务规则。

于 2016-12-10T13:16:45.220 回答
2

SQL 语句除了正确之外,还应尽可能易于阅读和表达简洁(因为它们代表单个原子操作,您需要完全理解它们以避免意外后果。)有时表达式更清楚地表述为右外连接。

但是一个总是可以转换成另一个,优化器对一个和另一个一样好。

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

于 2009-01-12T18:12:31.643 回答
2

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

于 2009-01-12T21:18:25.530 回答
1

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

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

于 2017-01-17T15:12:53.590 回答
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
于 2017-09-27T06:52:20.293 回答