INNER JOIN和OUTER JOIN有什么区别?


35

我是SQL新手,想知道这两种JOIN类型之间的区别是什么?

SELECT * 
FROM user u
INNER JOIN telephone t ON t.user_id = u.id

SELECT * 
FROM user u
LEFT OUTER JOIN telephone t ON t.user_id = u.id

什么时候应该使用其中一个?


6
这适合作为DBA问题吗?对我来说,这似乎是一个编码问题。
BlackICE 2011年

1
@David您对Meta
Sathyajith Bhat 2011年

如果您认为该网站有误,请@David然后是VtC。我们可以随时重新开放。
jcolebrand

3
我认为这是一个很好的问题,非常适合该网站。
datagod 2011年

除非新手DBA忙于调整数据库性能,否则需要将其移出DBA:P
AmDB 2012年

Answers:


32
  • 一个内部联接将只选择其中加入了钥匙在记录两个指定的表。
  • 一个左外连接将选择从第一个表中的所有记录,并在第二个表匹配连接键的任何记录。
  • 一个右外连接将选择从第二个表中的所有记录,并在第一台符合加入键的任何记录。

在第一个示例中,仅当用户存在至少一个电话记录时,才返回用户和电话号码的列表。

在第二个示例中,您将返回所有用户的列表,以及所有可用的电话记录(如果不可用,则将获得NULL电话值)。


13

每当有人问这个问题时,都有答案:http : //www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

希望它能帮助您理解,


3
我从事联接工作已有20年了,那些图对我来说似乎很令人困惑。
霍根

3
我和@Hogan在一起-ven图表不是对此最好的解释..显示返回哪些组合的网格可能会更好。

这说明您不了解维恩图。它们确实与联接的类型完美相关,但是请记住,它们是帮助了解新联接的工具。如果您已经学会了加入一个不同概念的联接,那么注定对您来说是陌生的。没问题,但这也不是图表有用性的指标。
JamesRyan

@jamesryan是不正确的,它们之间的关系不完美,联接类似于集合的笛卡尔积,而不是交集和并集,维恩图模拟仅在您通过唯一键联接时才起作用,如果您重复了键,则您将丢失笛卡尔积方面。
2016年

1
我非常不同意,维恩图已经有了很好定义的解释,设置了交集和并集。当您通过非唯一键进行联接时,联接不符合这种解释。我认为您对维恩图的解释过于广泛。
威尔

8

一个内连接,可以根据连接标准组合返回行。
一个外连接这些回报和所有行...
   ...从第一个表的左连接
   ...从一个第二个表右侧加入
   ...两个表的全加盟

选择何时使用一个或另一个是确定所需数据的问题。对于您的示例,如果您只需要电话中具有与用户ID匹配的用户ID的记录,则使用内部联接。如果您还希望包括没有匹配电话条目的用户行,那么左联接将是适当的。

有关更多信息,请参见StackOverflow上的此问题


7

如果您有两个如下表:

Table1 :   A1    B1          Table2  :    B2     C2 
           -     -                        -      -
           1     2                        1      1
           2     4                        2      4
           3     5                        5      2

如果使用内部联接,您将获得:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2

如果使用“完全外部联接”,您将获得:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2
 2      4    NULL     NULL
NULL   NULL    1       1

如果使用左外部联接,您将获得:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2
 2      4    NULL     NULL

6

明确设计外部联接以使其结果为空,因此通常应避免使用外部联接。从关系上讲,这是一种of弹枪的婚姻:它迫使表成为一种联合体-是的,我的意思是说联合体,而不是联接-即使有问题的表不符合通常的联合体要求。实际上,这是通过在进行联合之前用一个空值填充一个或两个表来实现的,从而使它们毕竟符合那些通常的要求。但是没有理由不应该使用适当的值而不是空值来进行填充,如以下示例所示:

SELECT SNO , PNO 
FROM   SP 
UNION  
SELECT SNO , 'nil' AS PNO 
FROM   S 
WHERE  SNO NOT IN ( SELECT SNO FROM SP )

或者,可以通过将SQL外连接运算符与结合使用来获得相同的结果COALESCE,如下所示:

SELECT SNO , COALESCE ( PNO , 'nil' ) AS PNO 
FROM ( S NATURAL LEFT OUTER JOIN SP ) AS TEMP

CJ Date在“ SQL和关系理论:如何编写准确的SQL代码”中对外部联接(4.6)的评论


5

内部联接是一个联接,其中显示的唯一结果是两个表中的键均在其中的结果。外部联接将显示一个表中所有键的结果,第一个表的左联接,第二个表的右联接。例如:

假设table1具有以下主键和数据对:(1,a),(2,b),(3,c)

我们还假设table2具有以下主键和数据对:(1,fun),(3,can),(4,事件)

因此,在主键上将table1与table2进行内部连接会产生以下结果三元组(首先是公用主键,第二个是第二个表,第二个是第二个表):(1,a,fun),( 3,c,可以)

主键上的table1到table2的左外部联接将产生以下结果三元组(与上面相同的格式):(1,a,fun),(2,b,NULL),(3,c,can)

主键上的table1到table2的右外部连接将产生以下结果三元组(与上面相同的格式):(1,a,fun),(3,c,can),(4,NULL,事件)

我希望这可以很好地解释这个概念。


4

让我尝试更直观地描述它。

内部联接显示具有一台或多部电话以及其电话号码的用户。

左外部联接还列出了没有电话的“用户”。


4

由于您已询问何时使用什么,因此这里有一个查询场景-根据需求选择要使用的内容。

数据:

表用户有10条记录。表Phoneno具有6条记录(具有1:1关系,这意味着PhoneNo中的一个条目将仅引用Users中的一个条目,PhoneNo中的仅一个条目可以引用Users中的给定条目)。

要求1:向所有用户显示其电话号码。忽略没有电话号码的用户。

查询:

SELECT u.uid, u.name, p.phonno 
  FROM user u 
INNER JOIN phones p ON p.uid = u.uid

结果:显示有电话号码的6个用户

要求2:向所有用户显示其电话号码。如果用户没有电话显示“ N / A”(不可用)

查询:

SELECT u.uid, u.name, ifnull(p.phonno,'N/A') 
  FROM user u 
LEFT OUTER JOIN phones p ON p.uid = u.uid

结果:

显示所有10条记录

注意:ifnull是MySql语法,用于转换null值。当phonno为null时,我使用此函数使数据库引擎显示“ N / A”。如果使用其他DBMS,请寻找适当的功能。在SQL Server中,您必须使用该CASE语句。

我希望这有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.