SQL进阶练习
练习题⽬目
查询" 01 “课程比” 02 "课程成绩⾼的学生的信息及课程分数
查询同时存在" 01 “课程和” 02 "课程的情况
查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )
查询不存在" 01 “课程但存在” 02 "课程的情况
1.查询" 01 "课程比" 02 "课程成绩⾼的学生的信息及课程分数
先查询01课程和02课程的信息,比较成绩,结果作为一个新表,然后和student进行表联结
(1)
select student.*
from student ,
(select s1.sid, s1.score
from (select * from sc where cid = '01') as s1
join (select * from sc where cid = '02') as s2 on s1.sid = s2.sid and s1.score > s2.score) as s3
where student.sid = s3.sid;
2.查询同时存在" 01 "课程和" 02 "课程的情况
(1)查出01和02的课程情况,再用聚合函数看课程数是否等于2
select stu.*
from student as stu
join
(select sid, count(sid) as course_num
from (select sid from sc where cid in('01','02')) as s1
group by sid having course_num = 2) as s2
on stu.sid = s2.sid;
(2)查出01和02的课程情况,看sid是否相等
select s1.sid, s1.score as s1_score, s2.score as s2_score from
(select sid, score from sc where cid = '01') as s1
join
(select sid, score from sc where cid = '02') as s2
on s1.sid = s2.sid;
3.查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
先查01的课程,02的课程,再以01为基准外联结
select s1.sid, s1.score as s1_score, s2.score as s2_score
from
(select sid, score from sc where cid = '01') as s1
left join
(select sid, score from sc where cid = '02') as s2
on s1.sid = s2.sid;
4.查询不存在" 01 "课程但存在" 02 "课程的情况
select * from sc
where sid not in(select sid from sc where cid = '01')
and cid = '02';
5.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
先求平均数,分组,再过滤 select stu.sid, stu.sname, round(avg(sc.score),2) as avg_score from student as stu,sc where sc.sid = stu.sid group by stu.sid, stu.sname having avg(sc.score) >= 60;
6.查询在 SC 表存在成绩的学生信息
两个表,表联结,去重distinct select distinct stu.* from student as stu join sc on sc.sid = stu.sid;
7.查询所有同学的学生编号、学⽣姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
select stu.sid, sname, count(sc.cid), sum(sc.score) from student as stu left join sc on stu.sid = sc.sid group by stu.sid, sname;
8.查询「李」姓老师的数量
模糊查询 select tid, tname, count(tname) from teacher where tname like ('李%') group by tid, tname;
9.查询学过「张三」老师授课的同学的信息
先查张三的tid,再查出cid,找出对应的sid,四表联结 select stu.* from student as stu join sc on sc.sid = stu.sid join course on sc.cid = course.cid join teacher on teacher.tid = course.tid where tname = '张三';
10.查询没有学全所有课程的同学的信息
--统计课程,取出课程数等于3的sid (1) select student.* from student join ( select sid, count(cid) as cid_num from sc group by sid having cid_num not in (3) ) as s1 on student.sid = s1.sid; (2) --排除法 select * from student where sid not in( select sid from sc group by sid having count(cid) = (select count(*) from course) );
11.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
查询学号01同学学习的课程cid,得出sid select student.* from student join sc on student.sid = sc.sid and cid in (select cid from sc where sid = '01');
12.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息
自联结cid,分别看表1(只有01)和表2(没有01),过滤课程数和01的总课程数不一样的其他sid,再与student联结 select s2.sid, student.sname from sc as s1 join sc as s2 on s1.cid = s2.cid and s1.sid = '01' and s2.sid != '01' join student on s2.sid = student.sid group by s2.sid, student.sname having count(s2.cid) = (select count(*) from sc where sid = '01' );
13.查询没学过"张三"老师讲授的任⼀门课程的学生姓名
先找"张三"老师 的teacher id 通过 teacher id找到对应的课程然后在学生分数表中根据course in 找到学过张三"老师 授课的学生群体再通过学生表not in找到没有学过张三"老师 授课的学生群体 (1) select sid, sname from student where sid not in (select sid from sc where cid = (select cid from course where tid in (select tid from teacher where tname = '张三'))); (2) select sname from student where sid not in (select sid from sc join course on sc.cid = course.cid join teacher on course.tid = teacher.tid and teacher.tname = '张三');
14.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
不用一次行把限制都写完,学会利用分组过滤 select stu.sid, stu.sname, round(avg(sc.score),2) from student as stu join sc on stu.sid = sc.sid where sc.score < 60 group by stu.sid, stu.sname having count(cid) >= 2;
15.检索" 01 "课程分数小于 60,按分数降序排列的学⽣生信息
select stu.*, sc.score from student as stu join sc on stu.sid = sc.sid where sc.cid = '01' and sc.score < 60 order by sc.score desc;
16.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
联结的目的为了快速查询 select sc.*, avg_sc from sc join (select sid, round(avg(sc.score),2) as avg_sc from sc group by sid) as s1 on sc.sid = s1.sid order by avg_sc desc, sid; select sname, a.score as '语文', b.score as '数学', c.score as '英语', avg(d.score) as '平均成绩' from student left join sc as a on a.sid = student.sid and a.cid = '01' left join sc as b on b.sid = student.sid and b.cid = '02' left join sc as c on c.sid = student.sid and c.cid = '03' left join sc as d on d.sid = student.sid group by sname, 语文, 数学, 英语 order by 平均成绩 desc;
17.查询各科成绩最高分、最低分和平均分:
以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀 为:>=90 要求输出课程号和选修⼈人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select sc.cid, c.cname, max(sc.score) as '最高分', min(sc.score) as '最低分', round(avg(sc.score),2) as '平均分', count(c.cid) as '选修人数', concat(round(sum(case when sc.score >= 60 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '及格率', concat(round(sum(case when sc.score >= 70 and sc.score < 80 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '中等率', concat(round(sum(case when sc.score >= 80 and sc.score < 90 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '优良率', concat(round(sum(case when sc.score >= 90 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '优秀率' from sc join course as c on sc.cid = c.cid group by sc.cid, c.cname order by 选修人数 desc, sc.cid;
18.按各科平均成绩进行排序,并显示排名, Score 重复时保留留名次空缺(成绩相同,排名一样)
平均成绩表自联结,外键比大小筛选,看出现的次数 (1) select s2.cid ,s2.avg_sc ,count(s2.avg_sc) as rank from (select cid,round(avg(score),2) as avg_sc from sc group by cid) as s1 join (select cid,round(avg(score),2) as avg_sc from sc group by cid) as s2 on s1.avg_sc >= s2.avg_sc group by s2.cid ,s2.avg_sc order by rank; (2)当字段有s2和s1时,表是整体看的,如果只有s1或者s2,表只看s1或者s2 select s2.cid ,s2.avg_sc ,count(distinct s1.avg_sc) as rank from (select cid,round(avg(score),2) as avg_sc from sc group by cid) as s1 join (select cid,round(avg(score),2) as avg_sc from sc group by cid) as s2 on s1.avg_sc >= s2.avg_sc group by s2.cid ,s2.avg_sc order by rank;
19.按各科平均成绩进行排序,并显示排名, Score 重复时不保留名次空缺(成绩相同,排名不一样)
成绩表当一个表,变量当一个表,用来初始化,用变量自增表示排名(因为不用在意空缺,变量相当于手动排名) select b.cid, b.avg_sc, @i := @i+1 as rank from (select @i := 0) as a, (select cid, avg(score) as avg_sc from sc group by cid order by avg_sc desc) as b;
20.查询学生的总成绩,并进行排名,总分重复时保留名次空缺(成绩相同,排名一样)
总成绩表自联结,以出现的次数当排名 select s2.sid, s2.sum_sc, count(distinct s1.sum_sc) as rank from (select sid, sum(score) as sum_sc from sc group by sid) as s1 join (select sid, sum(score) as sum_sc from sc group by sid) as s2 on s1.sum_sc >= s2.sum_sc group by s2.sid, s2.sum_sc order by rank;
21.查询学生的总成绩,并进行排名,总分重复时不保留名次空缺(成绩相同,排名不一样)
总成绩排序,用变量表示排名 select b.sid, b.sum_sc, @i := @i+1 as rank from (select @i := 0) as a, (select sid, sum(score) as sum_sc from sc group by sid order by sum_sc desc) as b;
22.统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0]及所占百 分比
select c.cid, cname, sum(case when score between 85 and 100 then 1 else 0 end) as '[100-85]人数', concat(round(sum(case when score between 85 and 100 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '[100-85]', sum(case when score between 70 and 85 then 1 else 0 end) as '[85-70]人数', concat(round(sum(case when score between 70 and 85 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '[85-70]', sum(case when score between 60 and 70 then 1 else 0 end) as '[70-60]人数', concat(round(sum(case when score between 60 and 70 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '[70-60]', sum(case when score between 0 and 60 then 1 else 0 end) as '[60-0]人数', concat(round(sum(case when score between 0 and 60 then 1 else 0 end) / count(sc.cid),2)*100,'%') as '[60-0]' from course as c left join sc on c.cid = sc.cid group by c.cid, cname;
23.查询各科成绩前三名的记录
(1)计算比自己分数大的记录有几条,如果小于3 就select,因为对前三名来说不会有3个及以上的分数比自己大了,最后再对所有select到的结果按照分数和课程编号排名即可。 (如果不保留名次空缺,则不符合要求) select * from sc where ( select count(*) from sc as a where sc.cid = a.cid and sc.score<a.score )< 3 order by cid asc, sc.score desc; (2)联合查询(但是如果保留名次空缺,则不符合要求) select a.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '01' order by sc.score desc limit 3) as a union select b.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '02' order by sc.score desc limit 3) as b union select c.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '03' order by sc.score desc limit 3) as c; -- (select cid,score from sc where cid = '01' order by score desc limit 3) union all (select cid,score from sc where cid = '02' order by score desc limit 3) union all (select cid,score from sc where cid = '03' order by score desc limit 3)
24.查询每门课程被选修的学生数
select cid, count(sid) as '选修人数' from sc group by cid;
25.查询出只选修两⻔课程的学⽣学号和姓名
select stu.sid, sname from student as stu join (select sid, count(cid) as c_num from sc group by sid) as a on stu.sid = a.sid and a.c_num = 2; --先查每个人的选修课数 select sid, count(cid) as c_num from sc group by sid;
26.查询男⽣、⼥⽣人数
select a.num as '男', b.num as '女' from (select count(ssex) as num from student where ssex = '男') as a, (select count(ssex) as num from student where ssex not in ('男')) as b; -- select ssex,count(*) from student group by ssex;27.查询名字中含有「风」字的学生信息
模糊查询 select * from student where sname like '%风%';
28.查询同名同性学生名单,并统计同名人数
count(*)会随选择字段改变 select sname,ssex, count(*) from student group by sname,ssex having count(*)>1; --自联结 select s1.sname, count(s1.sname) from student s1 join student s2 on s1.sname = s2.sname and s1.ssex = s2.ssex and s1.sid != s2.sid group by s1.sname;
29.查询 1990 年出生的学生名单
select * from student where Sage like '1990%' ; -- select * from student where year(sage) = 1990;
30.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select c.cid, c.cname, round(avg(sc.score),2) as avg_sc from course as c left join sc on c.cid = sc.cid group by c.cid, c.cname order by avg_sc desc, c.cid; -- select cid, avg(score) as avg_sc from sc group by cid order by avg_sc desc, cid;
31.查询平均成绩大于等于 85 的所有学⽣生的学号、姓名和平均成绩
select stu.sid, stu.sname, s1.avg_sc from student as stu join (select sid, avg(sc.score) as avg_sc from sc group by sid having avg_sc >= 85) as s1 on stu.sid = s1.sid; -- select sc.sid, stu.sname, round(avg(sc.score),2) as avg-sc from sc join student as stu on sc.sid = stu.sid group by sc.sid, stu.sname having avg_sc >= 85;
32.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
select sname, score from student as stu join sc on stu.sid = sc.sid join course on sc.cid = course.cid and cname = '数学' and score < 60;
33.查询所有学生的课程及分数情况(存在学⽣生没成绩,没选课的情况)
三次自联结 select stu.sid, stu.sname, a.score as '语文', b.score as '数学', c.score as '英语' from student as stu left join sc as a on a.sid = stu.sid and a.cid = '01' left join sc as b on b.sid = stu.sid and b.cid = '02' left join sc as c on c.sid = stu.sid and c.cid = '03' group by stu.sid,stu.sname, 语文, 数学, 英语 order by stu.sid;
34.查询任何⼀门课程成绩在 70 分以上的姓名、课程名称和分数
select stu.sname, c.cname, sc.score from student as stu join sc on stu.sid = sc.sid join course as c on sc.cid = c.cid and sc.score > 70;
35.查询不及格的课程
select distinct cname from sc join course on course.cid = sc.cid and sc.score < 60; -- select Student.Sname, Course.Cname, SC.score from Student,Course,SC where Student.SId = SC.SId and SC.CId = Course.CId and SC.score < 60;
36.查询课程编号为 01 且课程成绩在 80 分以上的学⽣生的学号和姓名
select stu.sid, stu.sname from student as stu join sc on sc.sid = stu.sid and sc.cid = '01' and sc.score >= 80;
37.求每门课程的学⽣⼈数
select cid,count(*) as num from sc group by cid;
38.成绩不重复,查询选修「张三」老师所授课程的学⽣中,成绩最高的学生信息及其成绩
select stu.*, sc.score from student as stu join sc on stu.sid = sc.sid join course as c on c.cid = sc.cid join teacher as t on t.tid = c.tid and t.tname = '张三' order by sc.score desc limit 1;39.成绩有重复的情况下,查询选修「张三」老师所授课程的学⽣生中,成绩最高的学生信息及其成绩
select stu.*, sc.score from student as stu join sc on stu.sid = sc.sid join course as c on c.cid = sc.cid join teacher as t on t.tid = c.tid and t.tname = '张三' and sc.score = ( select max(sc.score) from sc join course as c on c.cid = sc.cid join teacher as t on t.tid = c.tid and t.tname = '张三' ); -- select a.sname, b.score from student a join sc b on a.sid = b.sid and b.cid in (select cid from course where tid in (select tid from teacher where tname = '张三')) join (select cid, max(score) m from sc group by cid) c on b.cid = c.cid and b.score = c.m;
40.查询不同课程成绩相同的学生的学生编号、课程编号、学⽣成绩
(1) select distinct s1.sid, s1.cid, s1.score from sc as s1 join sc as s2 on s1.sid = s2.sid and s1.score = s2.score and s1.cid != s2.cid; (2) select a.cid, a.sid, a.score from sc as a inner join sc as b on a.sid = b.sid and a.cid != b.cid and a.score = b.score group by a.cid, a.sid, a.score;
41.查询每门课程成绩最好的前两名
(1) select * from sc where ( select count(*) from sc as a where sc.cid = a.cid and sc.score<a.score )< 2 order by cid asc, sc.score desc; (2) select a.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '01' order by sc.score desc limit 2) as a union select b.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '02' order by sc.score desc limit 2) as b union select c.* from (select sc.* from sc join course as c on c.cid = sc.cid and c.cid = '03' order by sc.score desc limit 2) as c; (3) (select CId,score from SC where CId = '01' order by score desc limit 2) union all (select CId,score from SC where CId = '02' order by score desc limit 2) union all (select CId,score from SC where CId = '03' order by score desc limit 2)
42.统计每门课程的学生选修人数(超过 5 人的课程才统计)。
select cid, count(sid) as num from sc group by cid having num > 5;
43.检索至少选修两门课程的学⽣学号
select sid, count(cid) as num from sc group by sid having num >= 2;
44.查询选修了全部课程的学⽣生信息
select stu.sid, stu.sname, stu.sage, stu.ssex, count(cid) as num from sc, student as stu where sc.sid = stu.sid group by stu.sid, stu.sname, stu.sage, stu.ssex having num = (select count(*) from course);
45.查询各学生的年龄,只按年份来算
select sid, sname, year(curdate()) - year(sage) as '年龄' from student;
46.按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一TIMESTAMPDIFF() 从日期时间表达式中减去间隔 https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
TIMESTAMPDIFF(*unit*,*datetime_expr1*,*datetime_expr2*)Returns
datetime_expr2−datetime_expr1, wheredatetime_expr1anddatetime_expr2are date or datetime expressions. One expression may be a date and the other a datetime; a date value is treated as a datetime having the time part'00:00:00'where necessary. The unit for the result (an integer) is given by theunitargument. The legal values forunitare the same as those listed in the description of theTIMESTAMPADD()function.select student.SId as 学生编号,student.Sname as 学生姓名, TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as 学生年龄 from student;
47.查询本周过⽣⽇的学⽣
返回⽇期从范围内的数字日历星期1到53
select * from student where weekofyear(sage) = weekofyear(curdate());48.查询下周过⽣⽇的学⽣
select * from student where weekofyear(sage) = weekofyear(curdate())+1;49.查询本月过⽣⽇的学⽣
select * from student where month(sage) = month(curdate());50.查询下月过⽣⽇的学⽣
select * from student where month(sage) = month(curdate())+1;
ose listed in the description of the TIMESTAMPADD() function.
select student.SId as 学生编号,student.Sname as 学生姓名, TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as 学生年龄 from student;[外链图片转存中…(img-2RippUZr-1596212425523)]
47.查询本周过⽣⽇的学⽣
返回⽇期从范围内的数字日历星期1到53
select * from student where weekofyear(sage) = weekofyear(curdate());48.查询下周过⽣⽇的学⽣
select * from student where weekofyear(sage) = weekofyear(curdate())+1;49.查询本月过⽣⽇的学⽣
select * from student where month(sage) = month(curdate());50.查询下月过⽣⽇的学⽣
select * from student where month(sage) = month(curdate())+1;
403

被折叠的 条评论
为什么被折叠?



