1.表的加法
表的加法是指按行,将表合并在一起,通过关键字union实现。现在,这里有两张格式一样的表,想要把两张表的数据合并起来,该如何操作?
![fa12be52549f6384a4c161af9f577ec3.png](https://i-blog.csdnimg.cn/blog_migrate/ee3756d1911ff7fd1d73c5e75ec2c056.png)
![722c8eaa4e1e316720bb2e49305445a5.png](https://i-blog.csdnimg.cn/blog_migrate/42514d1b146334ce4a034c39a773de02.png)
select 课程号,课程名称
from course
union -- 会删除重复的数据
select 课程号,课程名称
from course1;
select 课程号,课程名称
from course
union all -- 保留重复值
select 课程号,课程名称
from course1;
![52072d8de64f13c2e754a79a8f77c50c.png](https://i-blog.csdnimg.cn/blog_migrate/37ca0d6398a16a46a9436f3460209886.png)
![6100bad9df07de0e5d3b4bdbd4b16f6e.png](https://i-blog.csdnimg.cn/blog_migrate/b28ed0a06c894eabc7329cc806fe1561.png)
2.表的联结
![757a6b9e8dc687e1b244e762e51a9e39.png](https://i-blog.csdnimg.cn/blog_migrate/06c51b7986a3dab103602dc537f529f7.jpeg)
![f6af90f3066c75dc5b8e9c51eb878e99.png](https://i-blog.csdnimg.cn/blog_migrate/b52937d09fe6b1125d3fc23bca9adfe4.png)
![9c31099ca90ce2f76e81e3cea5e1915f.png](https://i-blog.csdnimg.cn/blog_migrate/78b21bb22667686381e464e3a13bded6.png)
/*
交叉联结,也叫笛卡尔积cross join
将表中的每一行与另一张表中的每一行合并在一起
如扑克牌:13张牌表示A,2,3...Q,K以及4种花色♠️,♥️,♣️,♦️,共4*13=52种花色
交叉联结是一切联结的基础,其他联结都是加了其他的筛选条件
*/
-- 内联结,查询出同时存在于两张表的数据,见结果1
select a.学号,a.姓名,b.课程号
from student as a inner join score as b
on a.学号 = b.学号; -- 通过学号这一列将两张表联结起来
-- 左联结,取出左侧表中全部的数据,右边的表中只选出与左边表相同的学号的行,left join,见结果2
select a.学号,a.姓名,b.课程号
from student as a left join score as b
on a.学号 = b.学号;
-- 返回只在a表中存在学号,在b表中不存在学号的行,见结果3
select a.学号,a.姓名,b.课程号
from student as a left join score as b
on a.学号 = b.学号
where b.学号 is null; -- null只能用用is/is not来判断,不能用=
-- 右联结,right join,见结果4
select a.学号,a.姓名,b.课程号
from student as a right join score as b
on a.学号 = b.学号;
-- 返回只在b表中存在学号,在a表中不存在学号的行,见结果5
select a.学号,a.姓名,b.课程号
from student as a right join score as b
on a.学号 = b.学号
where a.学号 is null;
-- 全联结,返回左,右表中所有行,若母行和另一表中有匹配时,该行合并,若无匹配的行,则用null填充
-- 但是mysql不支持全联结
![e8402f7ddf57e4158d0af0ec1b283e4d.png](https://i-blog.csdnimg.cn/blog_migrate/68e6e3ea0bd10a056b8a1d386815691c.png)
![ab6bb235937e08192d34db5d7838a85c.png](https://i-blog.csdnimg.cn/blog_migrate/f1b8be78ebcb7bfd2b97c66496883d9f.png)
![9e65d9808c2d63c7f6fe196ebf1aaa77.png](https://i-blog.csdnimg.cn/blog_migrate/05f2f1a101aa48ba12bf6343e6dc792b.png)
![c103a81dab4ce6e124691532d7f9c14b.png](https://i-blog.csdnimg.cn/blog_migrate/176739f3b898d3b11d6b8293c2ceb6c6.png)
![0a7fc396ade5e35322067894d2436762.png](https://i-blog.csdnimg.cn/blog_migrate/4b3ebd6c7131bd66da6a2cbb499c989b.png)
3.联结应用案例
![5aa41ea084f79606ec152ee6083d6318.png](https://i-blog.csdnimg.cn/blog_migrate/23c94445c851460e2071ab6863672985.png)
![f6bb55e4f7e054e828e88a2f2a9fc215.png](https://i-blog.csdnimg.cn/blog_migrate/a5e1fc6a36a4d6ec820674367a3bc7ea.png)
![f1389ff3d3d4005a60517b9b2b66746d.png](https://i-blog.csdnimg.cn/blog_migrate/36e177d689e0639ff6adadba1b07c87f.png)
-- 查询所有学生的学号,姓名,选课数,总成绩
/*
1.学号,姓名➡️student表
2.选课数(每个学生的选课数目:score表,按学号分组,对课程号计数count)
3.总成绩(每个学生的总成绩:score表,按学号分组,对成绩求和sum)
*/
-- 见结果1
select a.学号,a.姓名,count(b.课程号) as 选课数,sum(b.成绩) as 总成绩
from student as a left join score as b
on a.学号 = b.学号
group by a.学号;
-- 查询平均成绩大于85的所有学生的学号,姓名和平均成绩
/*
1.查询出所有学生的学号,姓名,平均成绩:学号,姓名在student表;平均成绩(每个学生的平均成绩:在score表,按学号分组,平均成绩:avg(成绩))
2.平均成绩大于85
*/
select a.学号,a.姓名,avg(b.成绩) as 平均成绩
from student as a left join score as b
on a.学号 = b.学号
where avg(b.成绩)>85 -- 此处错误,where子句后面不能使用汇总函数
group by a.学号
-- 见结果2
select a.学号,a.姓名,avg(b.成绩) as 平均成绩
from student as a left join score as b
on a.学号 = b.学号
group by a.学号
having avg(成绩)>85;
-- 查询学生的选课情况:学号,姓名,课程号,课程名称
-- 1.学号,姓名 from student
-- 2.课程号,课程名称 from course
-- 见结果3
select a.学号,a.姓名,c.课程号,c.课程名称
from student a inner join score b on a.学号 = b.学号 -- student a就是student as a
inner join course c on b.课程号 = c.课程号;
![8d7b91c959e9bbc92a91d10c47f69eb5.png](https://i-blog.csdnimg.cn/blog_migrate/7d904188c8f49d491211cf4e9ad6b2ba.png)
![61f6d6567405f444132e45aae45209a7.png](https://i-blog.csdnimg.cn/blog_migrate/d8c970b182add622746cf74d62385798.png)
![71b09daa2cebc21825ebc6ffdaca1366.png](https://i-blog.csdnimg.cn/blog_migrate/fd81a407f8c373792e8b72b8c95f5483.png)
4.case表达式
/* 就是if...else...的逻辑判断
case表达式
case when <判断表达式> then <表达式>
case when <判断表达式> then <表达式>
case when <判断表达式> then <表达式>
...
else <表达式>
end
*/
select 学号,课程号,成绩,
(case when 成绩 >= 60 then '及格'
when 成绩 < 60 then '不及格'
else null -- 可以不写,默认为null
end) as 是否及格 -- end不能省略
from score;
-- 查询出每门课程的及格人数和不及格人数
/*
1.查询出每门课程的人数
select 课程号,count(学号) as 人数
from score
group by 课程号;
2.上面代码每门课的人数的代码改为case表达式
*/
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 课程号;
/*
使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:
各分数段人数,课程号和课程名称
*/
select a.课程号,b.课程名称,
sum(case when 成绩 between 100 and 85 then 1
else 0
end) as '[85-100]',
sum(case when 成绩<85 and 成绩>70 then 1
else 0
end) as '[70-85]',
sum(case when 成绩<70 and 成绩>60 then 1
else 0
end) as '[60-70]',
sum(case when 成绩<60 then 1
else 0
end) as '[<60]'
from score as a right join course as b
on a.课程号 = b.课程号
group by a.课程号;,b.课程名称; -- select里的列名只能是group by里的列名,当用多个列来分组时,这几个列的值全部相同时才算一组
![1bf5aa19a4f3e46c04f6b0e3a71f06c1.png](https://i-blog.csdnimg.cn/blog_migrate/bb7d0bd16f6fe21768b8b5032a9e5889.png)
![6b978258a4d3958aabecb7c8d81cb573.png](https://i-blog.csdnimg.cn/blog_migrate/b252ea2918e43e48650b20e1083e8deb.png)
![5c9ead201ba8eca0b0938c44b83eab2c.png](https://i-blog.csdnimg.cn/blog_migrate/3230730ba566382ae4f839956967b374.png)
Sqlzoo练习题
Group by&having部分
![723425456150686301ee86c7080d2a58.png](https://i-blog.csdnimg.cn/blog_migrate/5cec4dc6fbddd6e7e5fac04f0cdbd0a4.jpeg)
当在select子句中同时出现列名&汇总函数,之后必须使用<group by 列名>的进行分组,否则会报错;若select子句之后只有汇总函数,则不需要group by 分组。
Aggregates function部分
![5f1d8ec5fb0215074a6297b71a25a428.png](https://i-blog.csdnimg.cn/blog_migrate/285e4eee1417e07ae6e834d7f9136a84.jpeg)
MySQL中的聚合函数有:
1.count() 所有记录数
2.count(*)所有非null记录数
3.avg() 某一列平均值
4.min() 某一列最小值
5.max() 某一列最大值
6.sum() 某一列总和
![b8670ef5fcc90e087a68533df53e6b54.png](https://i-blog.csdnimg.cn/blog_migrate/6bed74de963421d85570c6fe545e0e64.jpeg)
![d0af56605fce109f068e9bdb950e7f53.png](https://i-blog.csdnimg.cn/blog_migrate/0abe237c5e2ea0586c59121c6c9e4e62.jpeg)
Join部分
![2b632e9818ee09ef90f95aa30deb9ef2.png](https://i-blog.csdnimg.cn/blog_migrate/2fbc2dea693201d8be7ce4894facda59.jpeg)
前面的题都是使用的inner join内联结(简写为join)。
第13题使用的是左连接(left join),由于需要查询所有比赛的比分,所以需要连接表game与表goal(两张表均可见此张截图最上方),而goal表相当于只记录了有比分的比赛,对于0:0的比赛无法反映在goal这张表上;因此,需要使用左连接(left join)即取game的整张表,来与goal表连接,当整场比赛均无进球时,通过sum(case when(...) ) score1&sum(case when(...) ) score2可得比分为0:0并记录在查询所得的新表中。