SQL实战练习题1-45
SQL实战练习题
mysql1、01 "课程比" 02 "课程成绩高的学生信息和课程分数
方式一:
select a.sid as 学号,a.score as 01分数,b.score as 02分数,c.* FROM
(SELECT score,sid,cid FROM sc WHERE CId='01') as a
INNER JOIN (SELECT score,sid,cid FROM sc where CId='02') as b on a.sid=b.sid
INNER JOIN student as c on c.SId=a.sid where a.score>b.score;
方式二:
SELECT a.SId ,b.score "02",a.score "01",c.Sname FROM
(select SId,CId,score from sc where CId='01') as a
INNER JOIN
(select SId,cid,score from sc where CId='02' )as b on a.SId=b.SId
INNER JOIN student as c on c.SId=a.SId where a.score>b.score;
1.1 查询同时存在" 01 "课程和" 02 "课程的情况
方式一:
SELECT a.SId ,a.score "01",b.score "02" FROM
(select SId,CId,score from sc where CId='01') as a INNER JOIN
(select SId,cid,score from sc where CId='02' )as b on a.SId=b.SId
方式二:
select t1.sid,t1.score as 01课程分数,t2.score as 02课程分数
from (select SId ,score from sc where sc.CId='01')as t1 , (select SId ,score from sc where sc.CId='02') as t2
where t1.SId=t2.SId
1.2 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
SELECT * from
(SELECT * from sc where cid='01') as a
LEFT JOIN (SELECT * from sc where cid='02') as b on a.sid=b.sid
1.3 查询不存在" 01 "课程但存在" 02 "课程的情况
select *from sc
where SId not in (select SId from sc where sc.CId='01')and CId='02';
2、查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
SELECT t1.*,avg(t2.score) as 平均分 from student as t1 ,sc as t2
where t1.SId=t2.SId GROUP BY t1.SId having 平均分>60;
3、查询在 SC 表存在成绩的学生信息
select DISTINCT student.*from student ,sc where student.SId=sc.SId
4、所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为null)
select student.SId,student.Sname,t1.总分,t1.coursecount
from student ,(
select SC.SId,sum(sc.score) as 总分 ,count(sc.CId) as coursecount
from sc
GROUP BY sc.SId) as t1
where student.SId =t1.SId
补充没有成绩显示为0
SELECT t1.SId,t1.Sname,sum(case when t2.score is null then 0 else t2.score end),count(t2.cid)
from student as t1 LEFT JOIN sc as t2 on t1.SId=t2.SId group by t1.SId;
4.1 查有成绩的学生信息
方式一:
SELECT t1.* from student as t1 right JOIN sc as t2 on t1.SId=t2.SId group by t1.SId;
方式二:
select *from student where EXISTS (select * from sc where student.SId=sc.SId);
5、查询「李」姓老师的数量
Select count(*) from teacher where Tname like "李%";
6、查询学过「张三」老师授课的同学的信息
SELECT t1.*
from student as t1
INNER JOIN sc as t2 on t1.SId=t2.SId
INNER JOIN course as t3 on t2.CId=t3.CId
INNER JOIN teacher as t4 on t3.TId=t4.TId
where t4.Tname="张三";
7、查询没有学全所有课程的同学的信息
select count(*) from course; #所有课程数
-- 不完全解法:但这种解法得出来的结果不包括什么课都没选的同学。
select student.* from student INNER JOIN
(select sid,count(*) from sc
GROUP BY sid HAVING count(*)<(select count(*) from course)) as t
on t.sid=student.sid
-- 正确解法:
select DISTINCT student.*
from
(select student.SId,course.CId
from student,course ) as t1
LEFT JOIN (SELECT sc.SId,sc.CId from sc)as t2
on t1.SId=t2.SId and t1.CId=t2.CId,student
where t2.SId is null
and t1.SId=student.SId
8、查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
SELECT *from student where SId
in(SELECT DISTINCT SId from sc
where CId in ( SELECT CId from sc where SId='01') and SId!='01');
9、查询和" 01 "号的同学学习的课程完全相同的其他同学的信息
不能用01学生课程数量直接等于的做法反向思维,如果有一门不和01学生相同那一定不符合要求
select DISTINCT student.*
from (
select student.SId,t.CId
from student ,(select sc.CId from sc where sc.SId='01') as t) as t1 left join sc on t1.SId=sc.SId and t1.CId=sc.CId,student
where sc.SId is null
and t1.SId=student.SId
01学生选了01、02、03课程
1.选出所学课程不在01学生的范围内--排出
2.剩下学生肯定在01、02、03中某几门,判断所学课程是否等于01学号学生课程数即可
select * from student
where sid in (select sid sc
where sid!="01"
group by sid having count (distinct cid)=
(select count (distinct cid) from sc where sid="01"))
and sid not in (
select distinct sid from sc
where cid not in (
select cid from sc where sid="01")
10、查询没学过张三老师讲授的任一门课程的学生姓名
SELECT * from student where SId not in (SELECT SId from sc
INNER JOIN course on sc.CId=course.CId
INNER JOIN teacher on teacher.TId=course.TId
where teacher.Tname='张三')
11、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select student.SId,student.Sname,avg(sc.score)
from student ,sc
where student.SId=sc.SId
and sc.score<60
GROUP BY sc.SId
HAVING count(*)>=2
12、检索" 01 "课程分数小于 60,按分数降序排列的学生信息
SELECT student .* from student
INNER JOIN sc on student.SId=sc.SId
where sc.CId='01' and sc.score<60
ORDER BY sc.CId desc;
13、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
方式一:
select sc.SId,sc.CId,sc.score,t1.平均分
from sc INNER join
(select sc.SId,avg(sc.score) as 平均分 from sc GROUP BY sc.SId) as t1
on sc.SId =t1.SId
ORDER BY t1.平均分 DESC
方式二:
SELECT SId as '学号'
,MAX(case when CId='01' THEN score ELSE null end )'语文'
,MAX(case when CId='02' THEN score ELSE null end)'数学'
,max(case when CId='03' THEN score ELSE null end )'英语'
,avg(score) 平均成绩 from sc
GROUP BY SId
ORDER BY 平均成绩 DESC;
14、查询各科成绩最高分、最低分和平均分: 以如下形式显示:
课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,
优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
-- 及格率=count(>=60)/count(总数)
SELECT t1.CId,t2.Cname
,max(t1.score) '最高分'
,min(t1.score) '最低分'
,avg(t1.score) '平均分'
,sum(case when t1.score>=60 then 1 else 0 end)/COUNT(t1.SId) '及格'
,sum(case when t1.score>=70 and t1.score<80 then 1 else 0 end)/COUNT(t1.SId) '中等'
,sum(case when t1.score>=80 and t1.score<90 then 1 else 0 END)/COUNT(t1.SId) '优良'
,sum(case when t1.score>=90 then 1 else 0 end)/COUNT(t1.SId) '优秀'
from sc as t1
INNER JOIN course as t2 on t1.CId=t2.CId
GROUP BY CId
15、按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
select *,RANK()over(order by score desc)排名 from SC
15.1 按各科成绩进行排序,并显示排名, Score 重复时合并名次
select *,DENSE_RANK()over(order by score desc)排名 from SC
16、查询学生的总成绩,并进行排名,总分重复时保留名次空缺
select *,RANK()over(order by 总成绩 desc)排名
from (select SId,SUM(score)总成绩 from SC group by SId) as t1;
16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
select *,RANK()over(order by 总成绩 desc)排名
from (select SId,SUM(score)总成绩 from SC group by SId) as t1;
17、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
select course.CId,course.Cname,t1.*
from course LEFT JOIN (
select sc.CId,CONCAT(sum(case when sc.score>=85 and sc.score<=100 then 1 else 0 end )/count(*)*100,'%') as '[85-100]',
CONCAT(sum(case when sc.score>=70 and sc.score<85 then 1 else 0 end )/count(*)*100,'%') as '[70-85)',
CONCAT(sum(case when sc.score>=60 and sc.score<70 then 1 else 0 end )/count(*)*100,'%') as '[60-70)',
CONCAT(sum(case when sc.score>=0 and sc.score<60 then 1 else 0 end )/count(*)*100,'%') as '[0-60)'
from sc GROUP BY sc.CId) as t1 on course.CId=t1.CId
SELECT t2.cid,t2.cname
,SUM(case when t1.score<=100 and t1.score>85 then 1 else 0 END)/count(t1.sid) as '[100,85)'
,sum(case when t1.score<=85 and t1.score>70 then 1 ELSE 0 END)/count(t1.sid) as '[85,75)'
,sum(case when t1.score<=70 and t1.score>60 then 1 ELSE 0 END)/count(t1.sid) as '[70,60)'
,sum(case when t1.score<=60 and t1.score>0 then 1 ELSE 0 end) /count(t1.sid)as '[60,0)'
from sc as t1
INNER JOIN course as t2 on t1.cid=t2.cid
GROUP BY t2.cid,t2.cname
18、查询各科成绩前三名的记录
select * from(select *,rank()over (partition by CID order by score desc) 排名 from SC) as t1
where t1.排名<=3
19、查询每门课程被选修的学生数
SELECT sc.CId,course.Cname,count(DISTINCT sc.SId)
from sc,course where sc.CId=course.CId
GROUP BY sc.CId,course.Cname
20、查询出只选修两门课程的学生学号和姓名
SELECT t1.sid,t1.Sname
from student as t1 INNER JOIN sc as t2 on t1.sid=t2.SId
GROUP BY SId HAVING count(DISTINCT CId)=2
21、查询男生、女生人数
方式一:
SELECT Ssex,count(*) from student GROUP BY Ssex;
方式二:
SELECT
sum(case when Ssex='男' then 1 else 0 end) '男生人数',
sum(case when Ssex='女' then 1 else 0 end) '女生人数'
from student;
22、查询名字中含有「风」字的学生信息
select * from student where name like "%风%";
23、查询同名同性学生名单,并统计同名人数
select *
from student as t1 LEFT JOIN (
select Sname,Ssex,COUNT(*)同名人数 from Student group by Sname,Ssex) as t2
on t2.Sname =t1.Sname and t2.Ssex=t1.Ssex
where t2.同名人数>1
24、查询 1990 年出生的学生名单
SELECT * from student
where YEAR(Sage)='1990'
25、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT cid ,avg(score) 平均分 from sc
GROUP BY CId ORDER BY 平均分 desc,cid asc;
完善课程名称
SELECT sc.CId,course.Cname,avg(sc.score) '平均分'
from sc INNER JOIN course on sc.CId=course.CId
GROUP BY cid
ORDER BY 平均分 desc ,CId
26、查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
SELECT t1.sid,t1.sname,avg(t2.score)
from student as t1 INNER JOIN sc as t2
on t1.SId=t2.SId
GROUP BY t1.sid HAVING avg(t2.score)>85
27、查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
SELECT t1.Sname,t2.score
from student as t1
INNER JOIN sc as t2 on t1.SId=t2.SId
INNER JOIN course as t3 on t2.CId=t3.CId
where t3.Cname='数学' and t2.score<60
28、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
SELECT t1.SId,t1.Sname,t3.Cname,
max(case when t3.Cname='语文' then t2.score else null END)as '语文',
max(case when t3.Cname='数学' then t2.score else null END)as '数学',
max(case when t3.Cname='英语' then t2.score else null END)as '英语'
FROM student as t1
INNER JOIN sc as t2 on t1.SId=t2.SId
INNER JOIN course as t3 on t2.CId=t3.CId
GROUP BY t1.SId,t1.Sname
29、查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
方式一:
SELECT t1.Sname,t2.score,t3.Cname
from student as t1
INNER JOIN sc as t2 on t1.SId=t2.SId
INNER JOIN course as t3 on t2.CId=t3.CId
where t2.score>70
方式二:
select t1.Sname,t3.Cname,t2.score from Student t1,SC t2,Course t3
where t2.score>=70 and t1.SId = t2.SId and t2.CId=t3.CId;
30、查询存在不及格的课程
SELECT DISTINCT cid from sc where score<60;
补充
select DISTINCT sc.CId ,cname from SC
INNER JOIN course on course.CId=sc.cid
where sc.score <60
31、查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
方式一:
select SC.SId,S.Sname from Student S,SC
where SC.CId='01'and S.SId=SC.SId and SC.score>80;
方式二:
SELECT t1.sid,t1.sname from student t1
INNER JOIN sc t2 on t1.sid=t2.SId
where t2.cid='01' and t2.score>80
32、求每门课程的学生人数
select CId,count(SId) 人数 from SC group by CId;
33、成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select S.*,SC.score from Student S,Course C,Teacher T,SC
where C.CId=SC.CId and C.TId=T.TId and T.Tname='张三'
and S.SId =SC.SId order by SC.score desc limit 1;
34、成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select student.*, sc.score, sc.cid from student, teacher, course,sc
where teacher.tid = course.tid
and sc.sid = student.sid
and sc.cid = course.cid
and teacher.tname = "张三"
and sc.score = (select Max(sc.score)
from sc,student, teacher, course
where teacher.tid = course.tid
and sc.sid = student.sid
and sc.cid = course.cid
and teacher.tname = "张三");
35、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
select * from sc as t1 where exists
(select * from sc as t2 where t1.SId=t2.SId and t1.CId!=t2.CId and t1.score =t2.score )
36、查询每门功成绩最好的前两名
select * from sc as t1 where
(select count(*) from sc as t2 where t1.CId=t2.CId and t2.score >t1.score)<2
ORDER BY t1.CId
37、统计每门课程的学生选修人数(超过 5 人的课程才统计)
select CId, count(SId) from SC group by CId having count(SId) > 5;
38、检索至少选修两门课程的学生学号
SELECT sid, count(cid)from sc GROUP BY sid HAVING count(cid)>=2
39、查询选修了全部课程的学生信息
方式一:
select student.* from sc ,student
where sc.SId=student.SId
GROUP BY sc.SId
HAVING count(*) = (select DISTINCT count(*) from course )
方式二:
select S.* from Student S where S.SId in
(select SId from SC group by SId having count(CId) = (select DISTINCT count(*) from course ));
40、查询各学生的年龄,只按年份来算
select SId,Sname,TIMESTAMPDIFF(YEAR,Sage,now())年龄 from student;
41、按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
select SId,Sname,(DATE_FORMAT(NOW(),'%Y')-DATE_FORMAT(Sage,'%Y')
-(case when DATE_FORMAT(NOW(),'%m%d')>DATE_FORMAT(Sage,'%m%d') then 0 else 1 end)) 年龄
from student;
42、查询本周过生日的学生
select * from Student where WEEK(Sage)=WEEK(now());
43、查询下周过生日的学生
select * from Student where WEEK(Sage)=WEEK(now()) + 1;
44、查询本月过生日的学生
select * from Student where month(Sage)=month(now());
45、查询下月过生日的学生
select * from Student where month(Sage)=month(now()) + 1;