MySQL练习成果

SQL进阶练习

练习题⽬目

  1. 查询" 01 “课程比” 02 "课程成绩⾼的学生的信息及课程分数

  2. 查询同时存在" 01 “课程和” 02 "课程的情况

  3. 查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )

  4. 查询不存在" 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)查出0102的课程情况,再用聚合函数看课程数是否等于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)查出0102的课程情况,看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)计算比自己分数大的记录有几条,如果小于3select,因为对前三名来说不会有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_expr2datetime_expr1, where datetime_expr1 and datetime_expr2 are 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 the unit argument. The legal values for unit are the same as those listed in the description of the TIMESTAMPADD() 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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值