我是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


我什么时候应该使用一个或另一个?

评论

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

@David您对Meta的想法

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

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

除非有新手可以调整DB性能,否则需要将其移出DBA:P

#1 楼


内部联接将只选择两个指定表中已联接键的记录。
左外部联接将选择第一个表中的所有记录,以及第二个表中与联接键匹配的任何记录。
右外部联接将从第二个表中选择所有记录,以及第一个表中与联接的键匹配的所有记录。

在第一个示例中,您将仅返回一个列表用户和电话号码,如果该用户至少有一条电话记录。

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

#2 楼

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

希望它能帮助您理解,

评论


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

– Hogan
2011年1月4日18:32

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

–乔
2011年1月5日19:19



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

–詹姆斯·瑞安(JamesRyan)
2013年12月13日16:47



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

–将
16年5月31日在22:26

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

–将
16年1月1日在23:00

#3 楼

内部联接返回可以根据联接条件组合的行。
外部联接从第一个表返回这些行和所有行...
...左联接
。 ..从第二个表中进行正确联接
...从两个表中进行完全联接

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

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

#4 楼

如果您有2个如下表:

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


#5 楼

明确设计外部联接以使其结果为空,因此通常应避免使用外部联接。从关系上讲,这是一种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


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

#6 楼

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

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

也说table2具有以下主键和数据对:(1,fun),(3,can),(4,巧遇)

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

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

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

我希望这能很好地解释这一概念。

#7 楼

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

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

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

#8 楼

既然您已经询问了何时使用什么内容,那么这是一个带有查询的场景-根据需要选择要使用的内容。

数据:

表用户有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语法,用于转换空值。当phonno为null时,我使用此函数使数据库引擎显示“ N / A”。如果使用其他DBMS,请寻找适当的功能。在SQL Server中,必须使用CASE语句。

希望对您有所帮助。