学习内容:
1.表的加法
2.表的联结
3.联结应用
4.case表达式
一、如何合并两个表?
01.使用union all 合并后,两组数据将全部合并(若有重复数据,不会自动合并)
select 课程号,课程名称
from course
union all
select 课程号,课程名称
from course1;
02.若希望两个表合并且去重则直接使用 union 即可
select 课程号,课程名称
from course
union
select 课程号,课程名称
from course1;
二、表的联结 (join)
1.交叉联结 cross join
枚举了所以排列方式,会合并所有合并项的列
2.内联结 (inner join)
只取 与之有关的表 取其交集
select a.学好,a.姓名,b.课程号
from student as a inner join score as b
on a.学号=b.学号;
3.左联结 (left join)
取左边的表的数据 与 交集部分
select a.学号,a.姓名,b.课程号
from student as a left join score as b
on a.学号=b.学号
如果你只想取 左边表的数据, 去掉关联部分 可将右侧表数据标识 为 Null
select a.学号,a.姓名,b.课程号
from student as a left join score as b
on a.学号=b.学号
where b.学号=Null;
4.右联结 (right join)
取右边的表的数据 与 交集部分
select a.学号,a.姓名,b.课程号
from student as a right join score as b
on a.学号=b.学号
如果你只想取 右边表的数据, 去掉关联部分 可将右侧表数据标识 为 Null
select a.学号,a.姓名,b.课程号
from student as a right join score as b
on a.学号=b.学号
where a.学号=Null;
5.全联结(full join)
关联全部数据
三、重温sql运行顺序
select 查询结果 --第二步
from 从那张表中查询数据 (关联) --第一步
where 查询条件 (运算符,模糊查询)
group by 分组
having 对分组结果指定条件
order by 对查询结果排序 --第三步
limit 从查询结果取出指定行
四、联结应用案例
练习1:查询所有学生的学号,姓名,选课数,总成绩
select -- 查询结果是 学生学号,姓名,选课数需要汇总, 以及总成绩
from 需要关联[student]与[score]两个表
where --无条件查询
group by --需要按学号区分学生
having --无对分组结果指定条件
order by --无排序
limit --无从查询结果取出指定行
编写如下:
select a.学号,a.姓名,count(b.课程号)as'选课数',sum(b.成绩)as'总成绩'
from student as a left join score as b
on a.学号=b.学号
GROUP BY a.学号;
练习2:查询平均成绩大于85分的所有学生的学号,姓名 和 平均成绩
select -- 查询结果是 学生学号,姓名,计算平均成绩
from 需要关联[student]与[score]两个表
where --无条件查询
group by --按学生学号分组
having --平均分大于85分
order by --无排序
limit --无从查询结果取出指定行
编写如下:
select a.学号 , a.姓名 , avg(b.成绩)as'平均成绩'
from student as a left join score as b
on a.学号=b.学号
group by a.学号
having avg(b.成绩)>85;
练习3: 查询学生的选课情况:学号,姓名,课程号,课程名称
select -- 查询结果是 学生学号,姓名,课程号 和 课程名称
from 需要关联3各表[student]与[score]与[course]两个表
where --无条件查询
group by --无
having --无
order by --无排序
limit --无从查询结果取出指定行
编写如下:
select a.学号 , a.姓名 , b.课程号 , c.课程名称
from student as a inner join score as b inner join course as c;
五、case表达式
表达方式: sum(case when <判断表达式> then <表达式>
....
else <表达式>
end) as '表名字'
练习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】来统计各科成绩,分别统计各分数分段人数: 课程ID和课程名称
select a.学号,b.课程名称,
sum(case when 成绩 >= 85 then 1 else 0 end)as'100~85',
sum(case when 成绩 >= 70 and 成绩< 85 then 1 else 0 end)as'85~70',
sum(case when 成绩 >= 60 and 成绩< 70 then 1 else 0 end)as'70~60',
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.课程名称;
六、sql zoo
https://sqlzoo.net/wiki/The_JOIN_operation/zhsqlzoo.net
1.修改此SQL以列出 賽事編號matchid 和球員名 player ,該球員代表德國隊Germany入球的。要找出德國隊球員,要檢查: teamid = 'GER'
SELECT matchid, player
FROM goal
WHERE teamid = 'GER'
2.留意在 goal
表格中的欄位 matchid
,是對應表格game
的欄位id
。我們可以在表格 game中找出賽事1012的資料。
只顯示賽事1012的 id, stadium, team1, team2
SELECT id,stadium,team1,team2
FROM game
where id= 1012;
3.我們可以利用JOIN
來同時進行以上兩個步驟。
SELECT *
FROM game JOIN goal ON (id=matchid)
語句FROM 表示合拼兩個表格game 和 goal的數據。語句 ON 表示如何找出 game中每一列應該配對goal中的哪一列 -- goal的 id 必須配對game的 matchid 。 簡單來說,就是ON (game.id=goal.matchid)
以下SQL列出每個入球的球員(來自goal表格)和場館名(來自game表格)
修改它來顯示每一個德國入球的球員名,隊伍名,場館和日期。
select a.player, a.teamid, b.stadium, b.mdate
from goal as a inner join game as b
on b.id = a.matchid
where teamid = 'GER';
4.使用上題相同的 JOIN
語句,
列出球員名字叫Mario (player LIKE 'Mario%'
)有入球的 隊伍1 team1, 隊伍2 team2 和 球員名 player
select b. team1,b. team2,a. player
from goal as a inner join game as b
on b.id=a.matchid
where a. player like 'Mario%';
5.表格eteam
貯存了每一國家隊的資料,包括教練。你可以使用語句 goal JOIN eteam on teamid=id
來合拼 JOIN
表格goal
到 表格eteam
。
列出每場球賽中首10分鐘gtime<=10
有入球的球員 player
, 隊伍teamid
, 教練coach
, 入球時間gtime
SELECT a.player, a.teamid, b.coach, a.gtime
FROM goal as a inner join eteam as b
on a. teamid =b. id
WHERE gtime<=10 ;
6.列出'Fernando Santos'作為隊伍1 team1 的教練的賽事日期,和隊伍名。
select a.mdate,b.teamname
from game as a inner join eteam as b
on a.team1 = b.id
where b. coach='Fernando Santos';
7.列出場館 'National Stadium, Warsaw'的入球球員。
select b.player
from game as a inner join goal as b
on a.id = b.matchid
where a. stadium = 'National Stadium, Warsaw';
8.以下例子找出德國-希臘Germany-Greece 的八強賽事的入球
修改它,只列出全部賽事,射入德國龍門的球員名字。
SELECT distinct player
FROM game JOIN goal ON matchid = id
WHERE (teamid=team1 and team2='GER')or( teamid=team2 and team1='GER');
9.列出隊伍名稱 teamname 和該隊入球總數
SELECT teamname, count(teamname)
FROM eteam inner JOIN goal ON id=teamid
group BY teamname;
10.列出場館名和在該場館的入球數字。
SELECT stadium, count(stadium)as'入球數'
FROM game inner JOIN goal ON id=matchid
group BY stadium;
11.每一場波蘭'POL'有參與的賽事中,列出賽事編號 matchid, 日期date 和入球數字。
SELECT matchid, mdate, count(matchid)as'入球數'
FROM game JOIN goal ON matchid = id
WHERE (team1 = 'POL' OR team2 = 'POL')
group by matchid;
12.每一場德國'GER'有參與的賽事中,列出賽事編號 matchid, 日期date 和德國的入球數字。
select matchid, mdate,count(player)as'入球數'
from game join goal on matchid=id
where teamid = 'GER'
group by matchid;
13.查找出所有比赛的日期,每场比赛中对战双方各自进球数
select mdate,team1,
sum(case when team1=teamid then 1 else 0 end )as 'score1',
team2,
sum(case when team2=teamid then 1 else 0 end )as 'score2'
from game left join goal on matchid = id
group by id,mdate,team1,team2
order by mdate , id,team1,team2;