这一节会介绍表与表之间的运算,包括表的加法,表的联结和非常有用的CASE表达式。
1、表的加法
使用UNIOn子句对两张表进行合并计算,相当于在一张表里“添加行”。
具体见下图:
tips:
1)使用UNIOn合并两张表,重复的行会被删除,如果不想删除,则在UNIOn之后添加ALL关键字即可。
2)两张表的列数必须一致,对应列的数据类型也必须一致
3)ORDER BY子句只能用在SELECt子句的最后,且只能用一次
2、表的联结
表的联结就是将其他表的列添加过来,即进行“添加列”的计算,使用JION子句(可以理解为“添加,加入”的意思)在遇到“需要计算的数据被存储在不同的表里“这种情况时,使用JOIN子句就能方便地把需要的列合并在一张表里了。
联结分为交叉联结(CROSS JOIN)、内联结(INNER JOIN)、左联结(LEFT JOIN)、右联结(RIGHT JOIN)
交叉联结(CROSS JOIN) 又被称为笛卡尔积,是所有联结运算的基础。交叉联结的计算规则是对两张表的全部记录进行交叉组合,如果表A有5行记录,表B有8行记录,那么他们的交叉联结结果就会有5*8=40行记录。
而对于包含大量数据的表,交叉联结的计算结果是数量惊人的,而且很多记录也是没有用的。这就导致了实际应用中是很少用到交叉联结去处理数据,而是通过加上一定的条件,找到我们需要的数据即可。
根据限定条件的不同,常见的联结方式有内联结,左联结和右联结(后两者又可以被称为外联结,区别只是主表不同)
内联结SQL子句语法如下:
tips:
1)由于内联结涉及多张表,所以要在FROM子句里给每一个表写上别名,这样在后面指定条件的时候就可以使用“<表的别名>.<列名>"的方式进行区分
2)通过ON来指定两个表的联结条件,这里和关联子查询里的用法是一样的,注意ON必须书写在FROM和WHERe之间
3)WHERe、GROUP BY、HAVINg等子句依然可以使用
4)内联结只能取出同时存在两张表里的数据,只在某一张表中出现的数据则不会被选出来。
左联结SQL子句语法如下:
空值意味着左边的主表student里有学号为0004的学生,在右边的score表里没有对应记录。也就是说,主表里的所有数据都会被选取。
右联结SQL子句语法如下:
注意这里是以右边的score表为主表,所以学号一列选择的是b.学号,以体现查询结果是包含所有在score表中的数据,而student表不存在学号为0005的学生,所以姓名返回空值。
这里放一张各种联结的文氏图,方便大家理解记忆
3、联结应用案例
1)查询每个学生的选课数和总成绩(用到student表和score表)
2)查询平均成绩大于70分的同学姓名
3)查询每个学生都选了哪些课程(用到三张表,其中通过课程号把score表和course表联结起来)
4、CASE表达式
CASE是一种进行运算的功能,在SQL中十分重要,主要用在需要区分情况的时候使用,对应到编程环境下通常称为(条件)分支。
CASE表达式的语法分为简单CASE表达式和搜索CASE表达式两种,这里主要介绍后者,因为搜素CASE表达式包含了简单CASE表达式的所有功能。语法如下:
WHEN子句后面的判断表达式会进行逻辑判断,如果为‘真’则返回THEN后面的表达式,如果不为真那就进行下一条WHEN...THEN...的判断,直到最后一条WHEN子句都不为真,则返回ELSE子句的表达式。整个CASE表达式就运行完了。
由此可知,无论CASE表达式有多少分支,最终结果都是一个简单的值。
1)查询学生的及格情况
2)查询每门课的及格人数和不及格人数各有多少
tips:CASE表达式最后的ELSE子句不写则会默认为ELSE NULL,但是建议不要省略;END则不能省略,否则会报错;CASE表达式可以写在SQL语句的任意位置。
3)使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计各分数段人数,要求展示课程ID和课程名称
解题思路:遇到涉及自定义分组的问题,一定要用CASE表达式去做条件判断;如果涉及多个表,自然要用联结
注意:SELECT子句里的列名必须在GROUP BY子句里出现才可以,不能凭空写,否则会报错。另外GROUP BY后的列名就是分组条件,如果写了多个列名,分组条件是会发生改变的,所以如果要想不影响分组结果,几个列名之间必须是一一对应关系。
5、SQLZOO练习题
The JOIN operation/zhigs.sqlzoo.net记得使用DISTINCT去除重复的球员名字。
看到需要计算总数,且数据类型是字符串,记得使用COUNT函数