MySQL练习50道
MySQL练习
50道经典SQL练习题
数据表介绍
-
1.学⽣表 Student(SId,Sname,Sage,Ssex)
-
SId 学⽣编号
-
Sname 学⽣姓名
-
Sage 出⽣年⽉
-
Ssex 学⽣性别
-
2.课程表 Course(CId,Cname,TId)
-
CId 课程编号
-
Cname 课程名称
-
TId 教师编号
-
3.教师表 Teacher(TId,Tname)
-
TId 教师编号
-
Tname 教师姓名
-
4.成绩表 SC(SId,CId,score)
-
SId 学⽣编号
-
CId 课程编号
-
score 分数
建表语句
-
学⽣表 Student
create table Student( SId varchar(10), Sname varchar(10), Sage datetime, Ssex varchar(10) );
-
课程表 Course
create table Course( CId varchar(10), Cname varchar(10), TId varchar(10) );
-
教师表 Teacher
create table Teacher( TId varchar(10), Tname varchar(10) );
-
成绩表 SC
create table SC( SId varchar(10), CId varchar(10), score decimal(18,1) );
插入数据
-
学⽣表 Student
-- 学生表 Student insert into Student values('01' , '赵雷' , '1990-01-01' , '男'); insert into Student values('02' , '钱电' , '1990-12-21' , '男'); insert into Student values('03' , '孙风' , '1990-12-20' , '男'); insert into Student values('04' , '李云' , '1990-12-06' , '男'); insert into Student values('05' , '周梅' , '1991-12-01' , '女'); insert into Student values('06' , '吴兰' , '1992-01-01' , '女'); insert into Student values('07' , '郑竹' , '1989-01-01' , '女'); insert into Student values('09' , '张三' , '2017-12-20' , '女'); insert into Student values('10' , '李四' , '2017-12-25' , '女'); insert into Student values('11' , '李四' , '2012-06-06' , '女'); insert into Student values('12' , '赵六' , '2013-06-13' , '女'); insert into Student values('13' , '孙七' , '2014-06-01' , '女'); insert into Student values('14' , '李四' , '2012-06-06' , '女'); insert into Student values('14' , '李四' , '2012-09-04' , '女');
-
课程表 Course
-- 科⽬表 Course insert into Course values('01' , '语⽂' , '02'); insert into Course values('02' , '数学' , '01'); insert into Course values('03' , '英语' , '03');
-
教师表 Teacher
-- 教师表 Teacher insert into Teacher values('01' , '张三'); insert into Teacher values('02' , '李四'); insert into Teacher values('03' , '王五');
-
成绩表 SC
-- 成绩表 SC insert into SC values('01' , '01' , 80); insert into SC values('01' , '02' , 90); insert into SC values('01' , '03' , 99); insert into SC values('02' , '01' , 70); insert into SC values('02' , '02' , 60); insert into SC values('02' , '03' , 80); insert into SC values('03' , '01' , 80); insert into SC values('03' , '02' , 80); insert into SC values('03' , '03' , 80); insert into SC values('04' , '01' , 50); insert into SC values('04' , '02' , 30); insert into SC values('04' , '03' , 20); insert into SC values('05' , '01' , 76); insert into SC values('05' , '02' , 87); insert into SC values('06' , '01' , 31); insert into SC values('06' , '03' , 34); insert into SC values('07' , '02' , 89); insert into SC values('07' , '03' , 98);
练习题目
1.查询" 01 “课程⽐” 02 "课程成绩⾼的学⽣的信息及课程分数
-- 单独取出课程,再关联
select c.*,d.score01,d.score02,e.score as score03 from
Student as c
join
(
select a.SID ,a.score as score01,b.score as score02 from
(select * from SC where Cid='01') as a
left join
(select * from SC where Cid='02') as b
on a.Sid=b.SId
where a.score > if(b.score is null,0 ,b.score)
) as d
on c.SId=d.SId
join
(select * from SC where Cid='01') as e
on c.SId=e.Sid;
select a.*,b.score01,b.score02,b.score03 from
Student as a
join
(
select
Sid,
sum(case when CId='01' then score else 0 end) as score01,
sum(case when CId='02' then score else 0 end) as score02,
sum(case when CId='03' then score else 0 end) as score03
from
SC
group by Sid
having score01 > score02
) as b
on a.SId=b.SId;
2.查询同时存在" 01 “课程和” 02 "课程的情况
select
Sid,
sum(case when CId='01' then score else 0 end) as score01,
sum(case when CId='02' then score else 0 end) as score02,
sum(case when CId='03' then score else 0 end) as score03
from
SC
group by Sid
having score01 > 0 and score02 > 0;
3.查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )
select
Sid,
sum(case when CId='01' then score else 0 end) as score01,
sum(case when CId='02' then score else null end) as score02,
sum(case when CId='03' then score else 0 end) as score03
from
SC
group by Sid
having score01 > 0;
4.查询不存在" 01 “课程但存在” 02 "课程的情况
select
Sid,
sum(case when CId='01' then score else 0 end) as score01,
sum(case when CId='02' then score else null end) as score02,
sum(case when CId='03' then score else 0 end) as score03
from
SC
group by Sid
having score01 = 0 and score02 > 0
5.查询平均成绩⼤于等于 60 分的同学的学⽣编号和学⽣姓名和平均成绩
select
a.SId,
b.Sname,
avg(score) as avg_score
from
SC as a
join
Student as b
on
a.Sid=b.Sid
group by
a.SId,b.Sname
having
avg_score > 60;
PS:round(m,n)函数将字段m的查询结果保留小数点n位
6.查询在 SC 表存在成绩的学⽣信息
select distinct a.* from
Student as a
join
SC as b
on a.SId=b.SId;
select * from
Student
where Sid in (select distinct Sid from SC);
PS:DISTINCT 将后面的字段的查询结果进行去重。
7.查询所有同学的学⽣编号、学⽣姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
select a.SId,a.Sname,count(b.SId) as num,sum(b.score) as sum_score from
Student as a
left join
SC as b
on
a.SId=b.Sid
group by a.SId,a.Sname;
8.查询「李」姓⽼师的数量
select count(1) as num from
Teacher
where Tname like '李%'
9.查询学过「张三」⽼师授课的同学的信息
SELECT
*
FROM
Student
WHERE
SId IN (
SELECT
Sid
FROM
SC
WHERE
CId IN (
SELECT
Cid
FROM
Course
WHERE
TId = (
SELECT
TId
FROM
Teacher
WHERE
Tname = '张三'
)
)
)
10.查询没有学全所有课程的同学的信息
select a.SId,a.Sname,a.Sage,a.Ssex,count(b.SId) as num from
Student as a
left join
SC as b
on a.SId=b.SId
group by a.SId,a.Sname,a.Sage,a.Ssex
having num < (select count(1) from Course)
11.查询⾄少有⼀⻔课与学号为" 01 "的同学所学相同的同学的信息
select * from
Student
where
Sid in
(select distinct SId from SC
where Sid!='01' and CId in (select CId from SC where SId='01'))
12.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息
create view v_tmp as select CId from SC where SId='01';
select * from Student
where
SId in
(
SELECT
SId
FROM
SC
WHERE
SId IN (
SELECT
SId
FROM
SC
WHERE
SId != '01'
GROUP BY
SId
HAVING
count(1) = ( -- 1、第一次取出课程数量和01相同的学生
SELECT
count(1) AS num
FROM
v_tmp
)
)
AND CId IN (SELECT * FROM v_tmp)-- 2、取出至少有一个课程和01相同的学生
GROUP BY
SId
HAVING
count(1) = ( -- 3、取出和01完全相同的学生
SELECT
count(1) AS num
FROM
v_tmp
)
);
select * from
Student
where Sid in
(
select a.SId from
(select
Sid,
max(case when CId='01' then CId else '' end) as score01,
max(case when CId='02' then CId else '' end) as score02,
max(case when CId='03' then CId else '' end) as score03
from
SC
where SId!='01'
group by
SId) as a,
(select
Sid,
max(case when CId='01' then CId else '' end) as score01,
max(case when CId='02' then CId else '' end) as score02,
max(case when CId='03' then CId else '' end) as score03
from
SC
where SId='01'
group by
SId) as b
where
a.score01=b.score01 and a.score02=b.score02 and a.score03=b.score03
);
select
Sid,
group_concat(CId order by CId)
from
SC
group by
Sid
13.查询没学过"张三"⽼师讲授的任⼀⻔课程的学⽣姓名
select * from
Student
where
SId not in
(select Sid from
SC
where Cid in
(select Cid from
Course
where
TId = (select TId from Teacher where Tname = '张三')));
14.查询两⻔及其以上不及格课程的同学的学号,姓名及其平均成绩
select a.SId,a.Sname,b.avg_score from
Student as a
join
(select
SId,
-- count(case when score < 60 then 1 else null end) as num, -- 统计没几个科目的数量
sum(case when score < 60 then 1 else 0 end) as num,
avg(score) as avg_score
from
SC
group by SId
having num >= 2) as b
on a.SId=b.SId;
15.检索" 01 "课程分数⼩于 60,按分数降序排列的学⽣信息
select b.* from
SC as a
join
Student as b
on a.Sid=b.Sid
where Cid='01' and score < 60
order by a.score desc;
16.按平均成绩从⾼到低显示所有学⽣的所有课程的成绩以及平均成绩
select a.*,b.avg_score from
SC as a
join
(select
Sid,
avg(score) as avg_score
from
SC
group by Sid) as b
on a.SId=b.SId
order by b.avg_score desc;
17.查询各科成绩最⾼分、最低分和平均分: 以如下形式显示:课程 ID,课程 name,最⾼分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90要求输出课程号和选修⼈数,查询结果按⼈数降序排列,若⼈数相同,按课程号升序排列
select
CId,
max(score) as max_score,
min(score) as min_score,
avg(score) as avg_score,
round(count(case when score >=60 then 1 else null end) / count(1) *100,2) as p,
round(count(case when score >=70 and score<80 then 1 else null end) / count(1) *100,2) as p,
round(count(case when score >=80 and score<90 then 1 else null end) / count(1) *100,2) as p,
round(count(case when score >=90 then 1 else null end) / count(1) *100,2) as p
from
SC
group by
CId
order by count(1) desc ,CId asc;
concat()用作字符串拼接
concat(‘1’ , ’+’ , ’1’ , ‘=’ , ‘2’) ==> 1+1=2
case when 条件判断
CASE WHEN sc.score>=60 THEN 1 ELSE 0 END
意思是sc.score>=60这个条件成立时,返回1,不成立时返回0
18.按各科平均成绩进⾏排序,并显示排名, Score 重复时保留名次空缺
SELECT @i:=0;
select Cid,avg(score) as avg_score ,(@i:=@i+1) from
SC
group by
Cid
order by avg_score;
select c.*,d.rank from
SC as c
join
(select score,min(rank) as rank from (
select a.*,(@i:=@i+1) as rank from
SC as a,
(SELECT @i:=0) AS j
order by score
) as b
group by score) as d
on c.score = d.score
order by rank asc;
19.按各科平均成绩进⾏排序,并显示排名, Score 重复时不保留名次空缺
(@i:=@i+1)代表定义一个变量,每次叠加1;
(SELECT @i:=0) AS j 代表建立一个临时表,j是随便取的表名,但别名一定要的。
select Cid,avg(score) as avg_score ,(@i:=@i+1) from
SC,
(SELECT @i:=0) AS j
group by
Cid
order by avg_score;
20.查询学⽣的总成绩,并进⾏排名,总分重复时保留名次空缺
select a.*,(@i:=@i+1) as rank from
(
select SId,sum(score) as sum_score from
SC
group by
SId
order by sum_score desc
) as a,
(SELECT @i:=0) AS j
21.查询学⽣的总成绩,并进⾏排名,总分重复时不保留名次空缺
select a.*,(@i:=@i+1) as rank from
(
select SId,sum(score) as sum_score from
SC
group by
SId
order by sum_score desc
) as a,
(SELECT @i:=0) AS j
22.统计各科成绩各分数段⼈数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0]及所占百分⽐
select a.*,a.num / b.num * 100 as p from
(select
CId,
case
when score >= 0 and score <=60 then '[0-60]'
when score > 60 and score <=70 then '[60-70]'
when score > 70 and score <=85 then '[7-85]'
else '[85-10]' end as flow,
count(1) as num
from
SC
group by
Cid,
case
when score >= 0 and score <=60 then '[0-60]'
when score > 60 and score <=70 then '[60-70]'
when score > 70 and score <=85 then '[7-85]'
else '[85-10]' end
) as a
join
(select Cid,count(1) as num from
SC
group by Cid
) as b
23.查询各科成绩前三名的记录
再hive中使用row_number(()实现
(select * from
SC
where CId='01'
order by score
limit 3)
union all
(select * from
SC
where CId='02'
order by score
limit 3)
union all
(select * from
SC
where CId='03'
order by score
limit 3)
24.查询每⻔课程被选修的学⽣数
select Cid,count(1) as num from
SC
group by CId
25.查询出只选修两⻔课程的学⽣学号和姓名
select a.Sid,a.SName from
Student as a
join
(select SId,count(1) as num from
SC
group by SId
having num = 2
) as b
on a.Sid=b.Sid
26.查询男⽣、⼥⽣⼈数
select SSex,count(1) as num from
Student
group by
SSex
27.查询名字中含有「⻛」字的学⽣信息
select * from
Student
where
Sname like '%风%'
28.查询同名同性学⽣名单,并统计同名⼈数
select distinct a.* from
Student as a
join
Student as b
on a.SName=b.Sname and a.SId!=b.SId
select count(distinct a.SId) as num from
Student as a
join
Student as b
on a.SName=b.Sname and a.SId!=b.SId;
29.查询 1990 年出⽣的学⽣名单
select * from Student where year(Sage)='1990';
select * from Student where substring(Sage,1,4)='1990';
30.查询每⻔课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select CId,avg(score) as avg_score from
SC
group by CId
order by avg_score desc,Cid asc
31.查询平均成绩⼤于等于 85 的所有学⽣的学号、姓名和平均成绩
select a.SId,b.SName,avg(score) as avg_score from
SC as a
join
Student as b
on a.Sid=b.Sid
group by
a.SId,b.SName
having avg_score >= 85;
32.查询课程名称为「数学」,且分数低于 60 的学⽣姓名和分数
select b.Sname,a.score from
SC as a
join
Student as b
on a.Sid=b.Sid
where Cid = (select Cid from Course where CName = '数学')
and score >= 60
33.查询所有学⽣的课程及分数情况(存在学⽣没成绩,没选课的情况)
select * from
Student as a
left join
SC as b
on a.Sid=b.Sid
34.查询任何⼀⻔课程成绩在 70 分以上的姓名、课程名称和分数
select a.SName,c.Cname,b.score from
Student as a
join
SC as b
on
a.SId=b.SId
join
Course as c
on b.Cid=c.Cid
where a.Sid in (select distinct Sid from SC where score > 70) ;
select a.SName,c.Cname,b.score from
(
select * from
Student
where Sid in (select distinct Sid from SC where score > 70) -- 下层过滤器,减少关联的数据量
) as a
join
SC as b
on
a.SId=b.SId
join
Course as c
on b.Cid=c.Cid
35.查询不及格的课程
select * from
SC
where score < 60
36.查询课程编号为 01 且课程成绩在 80 分以上的学⽣的学号和姓名
select a.Sid,b.Sname,a.score from
SC as a
join
Student as b
on a.Sid=b.sid
where
CId='01' and score >= 80
37.求每⻔课程的学⽣⼈数
select CId,count(1) as num from
SC
group by CId
38.成绩不重复的情况下,查询选修「张三」⽼师所授课程的学⽣中,成绩最⾼的学⽣信息及其成绩
select * from
Student as a
join
(
select * from
SC
where Cid in(
select Cid from
Course
where Tid=(select TId from Teacher where Tname ='张三')
)
order by score desc
limit 1
) as b
on a.Sid=b.Sid;
39.成绩有重复的情况下,查询选修「张三」⽼师所授课程的学⽣中,成绩最⾼的学⽣信息及其成绩
40.查询不同课程成绩相同的学⽣的学⽣编号、课程编号、学⽣成绩
select a.* from
SC as a,
SC as b
where a.Sid!=b.Sid and a.CId!=b.Cid and a.score=b.score;
41.查询每⻔课程成绩最好的前两名
(select * from
SC
where CId='01'
order by score
limit 2)
union all
(select * from
SC
where CId='02'
order by score
limit 2)
union all
(select * from
SC
where CId='03'
order by score
limit 2);
42.统计每⻔课程的学⽣选修⼈数(超过 5 ⼈的课程才统计)。
select Cid,count(1) as num from
SC
group by
Cid
having num >5
43.检索⾄少选修两⻔课程的学⽣学号
select SId,count(1) as num from
SC
group by
SId
having num >= 2;
44.查询选修了全部课程的学⽣信息
select SId,count(1) as num from
SC
group by
SId
having num = (select count(1) from Course);
45.查询各学⽣的年龄,只按年份来算
select *,year(now()) - year(Sage) as age from
Student
46.查询各学⽣的年龄,按照出⽣⽇期来算,当前⽉⽇ < 出⽣年⽉的⽉⽇则,年龄减⼀
select
*,
year(now()) - year(Sage) as age ,
case when date_format(now(),'%m-%d') < date_format(Sage,'%m-%d') then year(now()) - year(Sage) - 1 else year(now()) - year(Sage) end as age
from
Student
47.查询本周过⽣⽇的学⽣
select * from
Student
where week(concat(year(now()),'-',date_format(Sage,'%m-%d')) )=week(now()) ;
48.查询下周过⽣⽇的学⽣
select *from
Student
where week(concat(year(now()),'-',date_format(Sage,'%m-%d')) ) =week(now())+1 ;
49.查询本⽉过⽣⽇的学⽣
select *from
Student
where month(concat(year(now()),'-',date_format(Sage,'%m-%d')) )=month(now()) ;
50.查询下⽉过⽣⽇的学⽣
select *from
Student
where month(concat(year(now()),'-',date_format(Sage,'%m-%d')))=month(now()) +1;