数据库中的连接运算,指的是将多个表的记录按照某种规则连接到一起。
连接运算可分为三种,分别是内连接、外连接和交叉连接(笛卡尔积),它们之间的区别,我们稍后会展开分析。
一、内连接
1. θ-连接
θ 表示的是待连接的两个表属性之间要满足的条件,比如 table1.field_a > table2.field_b
,即 table1 的 field_a 字段要大于 table2 的 field_b 字段。
通过具体的例子来解释会比较容易理解。
例如现在有如下两个表:
左边是学生的学号、姓名、性别和分数,右边是班级职务和最低分数要求。
假设现在要任命班长、体委和学委,要求列出所有满足成绩要求的职务委派选择。
那么就可以使用 θ-连接
来完成两个表的连接,这里的 θ 就是 Student.Score >= Position.Min_Score
,对应的 SQL 语句如下:
select * from Student inner join Position on Score >= Min_Score;
这样我们就把两个表连接到了一起,每一条记录代表职位的一种委派选择,结果如下:
2. 等值连接
θ-连接中的 θ 取等号时,就是等值连接。
考虑下面两张表:
左侧仍然是前面的 Student 表,右侧是签到表,记录每个同学晚自习的签到次数。
我们要同时列出每个同学的个人信息和对应的签到次数,那么就可以用等值连接来连接这两个表,条件为 Student.ID = Attendance.ID
,对应的 SQL 语句为:
select * from Student inner join Attendance on Student.ID = Attendance.ID;
连接结果如下:
因为这里两个表中的 ID 字段名字相同,因此必须在待比较的字段前加上表名,消除歧义。
3. 自然连接
仔细观察上面的连接结果,会发现最后出现了两列 ID 字段,而我们又知道这两列的值是一模一样的,因此实际上只需显示一列就够了。
这种情况下,使用自然连接会更为合适。自然连接是一种特殊的等值连接,它会比较两个表的所有同名字段,只有这些字段的值都相等的记录才会被连接到一起,并且最后的结果会消除重复的字段。
注意,自然连接有一个使用要求:待连接的两个表必须至少含有一个同名字段。
我们对上面的两个表使用自然连接,对应的 SQL 语句如下:
select * from Student natural join Attendance;
得到结果:
可以看到,两个表中 ID 字段相同的记录被连接到了一起,并且最后只保留了一列 ID 字段。
二、外连接
我们已经分析完了内连接,那么什么是外连接?为什么需要外连接?
考虑下面的这两张表:
跟最开始的例子一样,我们列出满足条件的班级职务委派的所有选择:
问题来了,这里只列出了满足条件的学生和职务之间的所有组合,问题1:没有班干部当选资格的小王不在结果中,问题2:没有合适人选的学习委员职务不在结果中。
如果我想要在结果中不仅看到职务委派的所有选择,还要看到哪些同学没有班干部的当选资格,以及哪些班级职务没有合适人选,那么该怎么实现?
外连接这时候就派上用场了。它不仅仅将两个表中满足条件的记录进行连接,还会将不满足条件的记录与空值构成的元组进行连接,显示在结果中。
外连接分为左外连接、右外连接和全外连接。
1. 左外连接
左表所有记录 + 右表匹配的记录。
如果左表中的某条记录在右表中没有匹配的记录可以连接,就将左表记录与空值元组进行连接。
接着上面的例子,SQL 语句为:
select * from Student left outer join Position on Score >= Min_Score;
连接结果:
即使小王没有可担任的职务,仍然将它与空值元组连接后列在结果中。
2. 右外连接
左表匹配的记录 + 右表所有记录。
如果右表中的某条记录在左表中没有匹配的记录可以连接,就将空值元组与右表记录进行连接。
SQL 语句为:
select * from Student right outer join Position on Score >= Min_Score;
连接结果:
即使学习委员这一职务没有合适的任选,但仍然用空值元组来连接它,列在结果中。
3. 全外连接
顾名思义,全外连接就是结合了左外连接和右外连接,只要是左表或右表中的记录,不管有没有匹配的记录可以进行连接,都会显示在结果中。对于没有匹配记录可以连接的,就用空值元组进行连接。
这个操作是 SQL 语言定义的,在 MySQL 的实现中并没有该操作,不过我们可以通过求左外连接和右外连接的并来得到等价的全外连接。
SQL 语句为:
select * from Student left outer join Position on Score >= Min_Score
union
select * from Student right outer join Position on Score >= Min_Score;
连接结果:
三、交叉连接
交叉连接就是笛卡尔积,即左表与右表所有记录的所有连接组合,不需要加任何条件就是求笛卡尔积,对应 SQL 语句:
select * from Student, Position;
结果如下:
四、总结
对两个表进行连接操作时,根据不同的需要,选择不同的连接方式。
如果要列出两个表所有记录的所有连接组合,使用交叉连接:
select * from table1, table2;
如果要对满足条件的记录进行连接,使用 θ-连接:
select * from table1 inner join table2 on condition;
如果要列出两个表中所有同名字段相等的记录,并且去除重复字段,使用自然连接:
select * from table1 natural join table2;
如果既要列出两表相匹配的记录,同时又要列出没有匹配项的记录,使用外连接:
select * from table1 left outer join table2;
select * from table2 right outer join table2;
希望通过以上具体的例子,能帮助你理解数据库的这几种连接操作。
作者:Wray Zheng
原文:http://www.codebelief.com/article/2018/03/understand-database-inner-join-outer-join-and-cross-join/