我想知道如何区分所有这些不同的连接......
9 回答
简单示例:假设您有一张Students
桌子和一张Lockers
桌子。在 SQL 中,您在连接中指定的第一个表Students
, 是LEFT表,第二个表Lockers
, 是RIGHT表。
每个学生都可以分配到一个储物柜,因此表格LockerNumber
中有一个列Student
。一个储物柜可能有多个学生,但尤其是在学年开始时,您可能会有一些没有储物柜的新生和一些没有分配学生的储物柜。
为了这个例子,假设你有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 个储物柜)。可能有用(通过过滤)作为将新学生与空储物柜匹配的起点。
有三种基本的连接类型:
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() 函数将这些值添加到范围的基准日期。
只有4种:
- 内连接:最常见的类型。为在连接条件上匹配的每对输入行生成一个输出行。
- 左外连接:与内连接相同,只是如果在右侧表中找不到任何匹配行,则输出包含左侧表中的值的行,
NULL
每个右表中的值。这意味着左侧表格中的每一行将在输出中至少出现一次。 - 右外连接:与左外连接相同,只是表的角色颠倒了。
- 全外连接:左右外连接的组合。两个表中的每一行都将在输出中至少出现一次。
“交叉连接”或“笛卡尔连接”只是没有指定连接条件的内部连接,导致输出所有行对。
感谢 RusselH 指出 FULL 连接,我省略了。
在 Wikipedia 上查看Join (SQL)
- 内连接 - 给定两个表,内连接返回两个表中存在的所有行
左/右(外部)连接 - 给定两个表返回存在于连接的左表或右表中的所有行,加上当连接子句匹配时将返回另一侧的行,否则将返回 null那些列
Full Outer - 给定两个表返回所有行,当左列或右列不存在时将返回空值
交叉连接 - 笛卡尔连接,如果不小心使用可能会很危险
让它更明显可能会有所帮助。一个例子:
表格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
LEFT JOIN
RIGHT JOIN
是s的类型OUTER JOIN
。
INNER JOIN
是默认值——两个表中的行必须匹配连接条件。
内连接:只显示行,当它有来自两个表的数据时。
外连接:(左/右):显示左/右表的所有结果与配对行(s),如果它存在与否。
首先你要明白join是做什么的?我们连接多个表并从连接的表中获取特定结果。最简单的方法是交叉连接。
假设 tableA 有两列 A 和 B。而 tableB 有三列 C 和 D。如果我们应用交叉连接,它将产生很多无意义的行。然后我们必须使用主键进行匹配以获取实际数据。
左:它将返回左表中的所有记录和右表中的匹配记录。
右:它将与左连接相反。它将返回右表中的所有记录和左表中的匹配记录。
内:这就像十字路口。它将只返回两个表中匹配的记录。
外:这就像联合。它将返回两个表中的所有可用记录。
有时我们不需要所有数据,而且我们应该只需要公共数据或记录。我们可以使用这些连接方法轻松获得它。记住左右连接也是外连接。
您只需使用交叉连接即可获取所有记录。但是当涉及到数百万条记录时,它可能会很昂贵。因此,通过使用左、右、内或外连接使其变得简单。
谢谢