左、右、外连接和内连接有啥区别? [复制]
Posted
技术标签:
【中文标题】左、右、外连接和内连接有啥区别? [复制]【英文标题】:What is the difference between Left, Right, Outer and Inner Joins? [duplicate]左、右、外连接和内连接有什么区别? [复制] 【发布时间】:2010-10-01 16:08:45 【问题描述】:我想知道如何区分所有这些不同的连接...
【问题讨论】:
来自编码恐怖A Visual Explanation of SQL Joins 也取决于你的理解水平,对于像你这样的人来说,这篇文章除了对可能不完全理解的人来说什么都不会加入它很清楚 这对我帮助很大...最简单的方法是制作测试表并与它们一起玩。 =P browse-tutorials.com/tutorial/mysql-joins The Coding Horror blog using Venn diagrams linked in the high upvoted 1st comment here被其作者后来在其cmets中否定。维恩图在讨论外连接和内连接时具有误导性和误用。在我在第一次评论中给出的重复链接中查看我的 cmets。 【参考方案1】:只有4种:
-
内连接:最常见的类型。为在连接条件上匹配的每对输入行生成一个输出行。
左外连接:与内连接相同,不同之处在于如果右侧表中没有找到匹配行的任何行,则输出包含该表中的值的行在左侧,
NULL
对应右侧表格中的每个值。这意味着左侧表格中的每一行将在输出中至少出现一次。
右外连接:与左外连接相同,只是表的角色颠倒了。
全外连接:左右外连接的组合。两个表中的每一行都会在输出中至少出现一次。
“交叉连接”或“笛卡尔连接”只是没有指定连接条件的内部连接,导致输出所有行对。
感谢 RusselH 指出 FULL 连接,我省略了。
【讨论】:
全外连接和交叉连接(笛卡尔积)怎么样? full 真的相当于两个外连接 FULL 是你搞砸内部连接时得到的结果,然后你在这里问一个问题“为什么我得到 N^2 行而不是 N”?然后每个人都会对你发火。【参考方案2】:LEFT JOIN
和 RIGHT JOIN
是 OUTER JOIN
s 的类型。
INNER JOIN
是默认值 -- 两个表中的行必须匹配连接条件。
【讨论】:
我无法相信这个答案怎么会有这么多的赞成票,同时又如此不完整。 我认为这是对原始问题的更好回答。【参考方案3】:查看Join (SQL) on Wikipedia
内连接 - 给定两个表,内连接返回两个表中存在的所有行左/右(外)连接 - 给定两个表返回存在于连接的左表或右表中的所有行,加上当连接子句匹配时将返回另一侧的行否则这些列将返回 null
Full Outer - 给定两个表返回所有行,当左列或右列不存在时将返回空值
交叉连接 - 笛卡尔连接,如果不小心使用会很危险
【讨论】:
【参考方案4】:简单示例:假设您有一个Students
表和一个Lockers
表。在 SQL 中,您在连接中指定的第一个表 Students
是 LEFT 表,第二个表 Lockers
是 RIGHT 表。
每个学生都可以分配到一个储物柜,所以Student
表中有一个LockerNumber
列。一个储物柜中可能有多个学生,但尤其是在学年开始时,您可能会有一些没有储物柜的新生和一些没有分配学生的储物柜。
就本示例而言,假设您有 100 名学生,其中 70 名学生有储物柜。您总共有 50 个储物柜,其中 40 个储物柜至少有 1 个学生,10 个储物柜没有学生。
INNER JOIN
相当于“告诉我所有带储物柜的学生”。
任何没有储物柜的学生,或没有学生的任何储物柜都丢失了。返回 70 行
LEFT OUTER JOIN
将是“向我展示所有学生,如果他们有相应的储物柜,请带上他们的储物柜”。
这可能是一个普通的学生名单,或者可以用来识别没有储物柜的学生。 返回 100 行
RIGHT OUTER JOIN
将是“显示所有储物柜,以及分配给它们的学生(如果有的话)”。
这可用于识别没有分配学生的储物柜,或有太多学生的储物柜。 返回 80 行(40 个储物柜中的 70 名学生的列表,加上没有学生的 10 个储物柜)
FULL OUTER JOIN
会很傻,可能没什么用处。
类似“显示所有学生和所有储物柜,并在可以匹配的位置”返回 110 行(所有 100 名学生,包括没有储物柜的学生。另外没有学生的 10 个储物柜)
CROSS JOIN
在这种情况下也相当愚蠢。 它不使用学生表中链接的lockernumber
字段,因此您基本上最终会得到一个包含所有可能的学生到-储物柜配对,无论它是否真的存在。返回 5000 行(100 个学生 x 50 个储物柜)。作为一个起点,将新学生与空储物柜匹配起来可能很有用(通过过滤)。
【讨论】:
使用您的示例,CROSS join 将作为创建储物柜分配的起点非常有用:从所有可能的组合开始,然后使用其他条件从列表中过滤结果。 不错的答案。我相信当您需要大量记录时,Cross Join 最常用于从几行生成测试数据。 FULL OUTER JOINS 在搜索孤立数据或比较同一数据集的不同版本时非常有用。 交叉加入又名笛卡尔积 我认为您开始查询的方式会影响连接类型的结果。例如,SELECT * FROM students RIGHT OUTER JOIN lockers...
将产生与SELECT * FROM lockers RIGHT OUTER JOIN students...
不同的结果。很好的答案,但希望看到它更新完整的SQL
查询【参考方案5】:
有三种基本的连接类型:
INNER
join 比较两个表,只返回匹配的结果。当第一个表中的记录与第二个表中的多个结果匹配时,它们会重复。 INNER 联接往往会使结果集更小,但由于记录可以重复,因此不能保证这一点。
CROSS
join 比较两个表并返回两个表中所有可能的行组合。您可以从这种连接中获得很多甚至可能没有意义的结果,因此请谨慎使用。
OUTER
join 比较两个表并在匹配可用时返回数据,否则返回 NULL 值。与 INNER 连接一样,当它匹配另一张表中的多条记录时,这将复制一张表中的行。 OUTER 联接倾向于使结果集更大,因为它们本身不会从集中删除任何记录。您还必须限定 OUTER 连接以确定何时何地添加 NULL 值:
LEFT
表示无论如何保留第一个表中的所有记录,并在第二个表不匹配时插入 NULL 值。
RIGHT
表示相反的意思:无论如何保留第二张表中的所有记录,并在第一张表不匹配时插入 NULL 值。
FULL
表示保留两个表中的所有记录,如果不匹配,则在任一表中插入 NULL 值。
您经常会看到语法中省略了OUTER
关键字。相反,它将只是“LEFT JOIN”、“RIGHT JOIN”或“FULL JOIN”。这样做是因为 INNER 和 CROSS 连接对于 LEFT、RIGHT 或 FULL 没有任何意义,因此它们本身就足以明确指示 OUTER 连接。
以下是您可能希望使用每种类型的示例:
INNER
:您希望从“Invoice”表中返回所有记录,以及它们对应的“InvoiceLines”。这假定每张有效的发票都至少有一行。
OUTER
:您想要返回特定发票的所有“InvoiceLines”记录,以及它们对应的“InventoryItem”记录。这是一家还销售服务的企业,因此并非所有 InvoiceLines 都有 IventoryItem。
CROSS
:您有一个包含 10 行的数字表,每行包含值 '0' 到 '9'。您想创建一个日期范围表来加入,以便在该范围内的每一天都有一条记录。通过重复将此表与自身交叉连接,您可以根据需要创建任意数量的连续整数(假设您从 10 的 1 次方开始,每个连接都会将 1 添加到指数)。然后使用 DATEADD() 函数将这些值添加到该范围的基准日期。
【讨论】:
不错。如果你只写“JOIN”,我只会添加它,这意味着 INNER JOIN。【参考方案6】:内连接:只显示行,当它有来自两个表的数据时。
外连接:(左/右):显示左/右表的所有结果与配对行(s),如果它存在。
【讨论】:
【参考方案7】:让它更显眼可能会有所帮助。一个例子:
表 1:
ID_STUDENT STUDENT_NAME
1 Raony
2 Diogo
3 Eduardo
4 Luiz
表 2:
ID_STUDENT 储物柜
3 l1
4 l2
5 l3
当我做的时候我得到了什么:
-Inner join of Table 1 and Table 2:
- Inner join returns both tables merged only when the key
(ID_STUDENT) exists in both tables
ID_STUDENT STUDENT_NAME LOCKER
3 Eduardo l1
4 Luiz l2
-Left join of Table 1 and Table 2:
- Left join merges both tables with all records form table 1, in
other words, there might be non-populated fields from table 2
ID_ESTUDANTE NOME_ESTUDANTE LOCKER
1 Raony -
2 Diogo -
3 Eduardo l1
4 Luiz l2
-Right join of table 1 and table 2:
- Right join merges both tables with all records from table 2, in
other words, there might be non-populated fields from table 1
ID_STUDENT STUDENT_NAME LOCKER
3 Eduardo l1
4 Luiz l2
5 - l3
-Outter join of table 1 and table 2:
- Returns all records from both tables, in other words, there
might be non-populated fields either from table 1 or 2.
ID_STUDENT STUDENT_NAME LOCKER
1 Raony -
2 Diogo -
3 Eduardo l1
4 Luiz l2
5 - l3
【讨论】:
【参考方案8】:首先你要明白join是做什么的?我们连接多个表并从连接的表中获取特定结果。最简单的方法是cross join。
假设 tableA 有两列 A 和 B。而 tableB 有三列 C 和 D。 如果我们应用交叉连接,它会产生很多无意义的行。然后我们必须使用主键进行匹配才能获取实际数据。
左:会返回左表的所有记录和右表的匹配记录。
右:它将与左连接相反。它将返回右表中的所有记录和左表中的匹配记录。
内:这就像十字路口。它将只返回两个表中匹配的记录。
外:这就像联合。它将返回两个表中的所有可用记录。
有时我们不需要所有数据,而且我们应该只需要常用数据或记录。我们可以使用这些连接方法轻松获得它。记住左右连接也是外连接。
您可以使用交叉连接获取所有记录。但是当涉及到数百万条记录时,它可能会很昂贵。因此,使用左、右、内或外连接使其变得简单。
谢谢
【讨论】:
【参考方案9】:SQL JOINS 区别:
很容易记住:
INNER JOIN
只显示两个表共有的记录。
OUTER JOIN
两个表的所有内容无论是否匹配都会合并在一起。
LEFT JOIN
与 LEFT OUTER JOIN
相同 - (从第一个(最左边的)表中选择与右表记录匹配的记录。)
RIGHT JOIN
与 RIGHT OUTER JOIN
相同 - (从第二个(最右侧)表中选择与左表记录匹配的记录。)
【讨论】:
有一种正确且相关的方式来标记维恩图圈,但这不是。圆圈不是输入表。结果行也不是输入行,因此您的描述在那里是错误的。这也不清楚——你没有解释“两者共同”、“匹配”、“合并”。以上是关于左、右、外连接和内连接有啥区别? [复制]的主要内容,如果未能解决你的问题,请参考以下文章