数据表(4张)及数据情况:
搭建数据表数据参考:空杯希望:转行数据分析师专栏(SQL篇)-01SQL入门zhuanlan.zhihu.com
一、表的加法
1、先新建一个表course1(和course表数据结构一致,但数据不一样)
2、union:将course和course1表数据合并
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
-- 对重复的数据(0001,语文,教师号)只保留一行
SELECT 课程号,课程名称
FROM course
UNION
SELECT 课程号,课程名称
FROM course1
-- 保留重复的数据
SELECT 课程号,课程名称
FROM course
UNION ALL
SELECT 课程号,课程名称
FROM course1
二、表的联结
1、内联结(inner join,默认为join)
只返回两个表中联结字段相等的行
案例:查询有考试记录的每个学生考过哪些课程,列名包括学号,姓名,课程号
-- 1、0002学号在score表里没有0001课程号的数据,所以查询结果不存在这行数据
-- 2、0004学号在score表里没有任何课程号的数据,所以查询结果没有这位学生数据
SELECT a.学号,a.姓名,b.课程号
FROM student AS a
INNER JOIN score AS b
ON a.学号 = b.学号
2、左联结(left join)
返回包括左表中的所有记录和右表中联结字段相等的记录
案例1:查询全部学生的学号,姓名及考试科目(课程号)
-- 0004学号在score表虽然没有记录,但因为是左表的数据,所以会保留在查询结果
SELECT a.学号,a.姓名,b.课程号
FROM student AS a
LEFT JOIN score AS b
ON a.学号 = b.学号
案例2:不显示案例1王思聪的数据
SELECT a.学号,a.姓名,b.课程号,b.成绩
FROM student AS a
LEFT JOIN score AS b
ON a.学号 = b.学号
WHERE b.学号 IS NOT NULL
3、右联结(right join)
返回包括右表中的所有记录和左表中联结字段相等的记录
案例:查询考过课程的学生信息,列名包括学号、姓名和课程号、分数(跟左联结的案例2结果一直)
SELECT a.学号,a.姓名,b.课程号,b.成绩
FROM student AS a
RIGHT JOIN score AS b
ON a.学号 = b.学号
4、全联结(full join)
存在匹配,匹配显示;同时,将各个表中不匹配的数据与空数据行匹配进行显示。可以看成是左外连接与右外连接的并集。
注意:Mysql不支持full join
5、一张图总结SQL联结
三、联结应用综合案例
1、查询所有学生的学号、姓名、选课数、总成绩
-- 1)学号、姓名(学生表student)
-- 2)选课数(每个学生的选课数目:成绩表score,按学号分组,对课程号计数count)
-- 3)总成绩(每个学生的总成绩:成绩表score,按学号分组,对成绩求和sum)
SELECT st.学号,st.姓名,count(课程号),sum(成绩)
FROM student as st LEFT JOIN score as sc on st.学号=sc.学号
GROUP BY 学号
2、查询平均成绩大于85的所有学生的学号、姓名和平均成绩
-- 1)查询出所有学生的学号,成名,平均成绩,学号,姓名(在学生表student)
-- 平均成绩(每个学生的平均成绩:在成绩表score,按学号分组,平均成绩:avg(成绩))
-- 2) 平均成绩>85
SELECT st.学号,st.姓名,avg(成绩)
FROM student AS st
RIGHT JOIN score AS sc ON st.学号 = sc.学号
GROUP BY 学号
HAVING AVG(成绩) > 85;
四、case表达式
案例1:查询出每门课程的及格人数和不及格人数
SELECT 课程号,
SUM(CASE WHEN 成绩>=60 THEN 1 ELSE 0 END) AS 及格人数,
SUM(CASE WHEN 成绩<60 THEN 1 ELSE 0 END) AS 不及格人数
FROM score
GROUP BY 课程号
案例2:使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分段人数,课程号和课程名称。
SELECT SUM(CASE WHEN sc.成绩<=100 AND sc.成绩>=85 THEN 1 ELSE 0 END)AS '[100-85]',
SUM(CASE WHEN sc.成绩>=70 AND sc.成绩<85 THEN 1 ELSE 0 END)AS '[85-70]',
SUM(CASE WHEN sc.成绩<70 AND sc.成绩>=60 THEN 1 ELSE 0 END)AS '[70-60]',
SUM(CASE WHEN sc.成绩<60 THEN 1 ELSE 0 END)AS '[<60]'
,sc.课程号,co.课程名称
FROM course as co RIGHT JOIN score as sc ON co.课程号=sc.课程号
GROUP BY sc.课程号,co.课程名称
五、练习题
链接:The JOIN operation/zhsqlzoo.net
往期数据分析专栏:转行数据分析师专栏(Excel篇)zhuanlan.zhihu.com