MySQL练习题

create database alibaba;

use alibaba;

create table student(s_id varchar(10),s_name varchar(10),s_age date,s_sex varchar(10)) engine=InnoDB default charset utf8;
insert into student(s_id,s_name,s_age,s_sex)
values(‘01’ , ‘赵雷’, ‘1990-01-01’ , ‘男’),
(‘02’ , ‘钱电’ , ‘1990-12-21’ , ‘男’)
,(‘03’ , ‘孙风’ , ‘1990-05-20’ , ‘男’)
,(‘04’ , ‘李云’ , ‘1990-08-06’ , ‘男’)
,(‘05’ , ‘周梅’ , ‘1991-12-01’ , ‘女’)
,(‘06’ , ‘吴兰’ , ‘1992-03-01’ , ‘女’)
,(‘07’ , ‘郑竹’ , ‘1989-07-01’ , ‘女’)
,(‘08’ , ‘王菊’ , ‘1990-01-20’ , ‘女’);
select * from student;

create table course(c_id varchar(10),c_name varchar(10),t_id varchar(10)) engine=InnoDB default charset utf8;
insert into course values(‘01’ , ‘语文’ , ‘02’),
(‘02’ , ‘数学’ , ‘01’),
(‘03’ , ‘英语’ , ‘03’);
select * from course;

create table teacher(t_id varchar(10),t_name varchar(10)) engine=InnoDB default charset utf8;
insert into teacher values(‘01’ , ‘张三’)
,(‘02’ , ‘李四’)
,(‘03’ , ‘王五’);
select * from teacher;

create table stu_sco(s_id varchar(10),c_id varchar(10),score decimal(18,1)) engine=InnoDB default charset utf8;
insert into stu_sco values
(‘01’ , ‘01’ , 80)
,(‘01’ , ‘02’ , 90)
,(‘01’ , ‘03’ , 99)
,(‘02’ , ‘01’ , 70)
,(‘02’ , ‘02’ , 60)
,(‘02’ , ‘03’ , 80)
,(‘03’ , ‘01’ , 80)
,(‘03’ , ‘02’ , 80)
,(‘03’ , ‘03’ , 80)
,(‘04’ , ‘01’ , 50)
,(‘04’ , ‘02’ , 30)
,(‘04’ , ‘03’ , 20)
,(‘05’ , ‘01’ , 76)
,(‘05’ , ‘02’ , 87)
,(‘06’ , ‘01’ , 31)
,(‘06’ , ‘03’ , 34)
,(‘07’ , ‘02’ , 89)
,(‘07’ , ‘03’ , 98);
select * from stu_sco;

#######################################################################################################################################################
#–1、查询"01"课程比"02"课程成绩高的学生信息及课程分数
– 我们新建一个表,用来存储每个学生的id以及“01”课程分数
select s_id,c_id,score as score_01 from stu_sco where c_id=‘01’;

select s_id,c_id,score as score_02 from stu_sco where c_id=‘02’;

– 然后我们就可以通过多表查询得到那些"01"课程比"02"课程成绩高的学生s_id
select a.s_id from (select s_id,c_id,score as score_01 from stu_sco where c_id=‘01’) a
inner join
(select s_id,c_id,score as score_02 from stu_sco where c_id=‘02’)b
on a.s_id=b.s_id and a.score_01>b.score_02;

– 得到"01"课程比"02"课程成绩高的学生s_id后,利用这些s_id
select a.*,c.c_id,c.score from student a left join
(select a.s_id from (select s_id,c_id,score as score_01 from stu_sco where c_id=‘01’) a
inner join
(select s_id,c_id,score as score_02 from stu_sco where c_id=‘02’)b
on a.s_id=b.s_id and a.score_01>b.score_02) b
on a.s_id=b.s_id
inner join stu_sco c on b.s_id=c.s_id;

– 上面的方法的逻辑理解简单,便于根据类似的题型作出灵活修改,但是写起来繁琐。
– 如果题目不要求查询出目标对象的所有课程,只要求查询出‘01’和‘02’课程,我们可以做两次内连接,学生表内连接到分数表a,再内连接到分数表b,再作筛选,是可以实现相同的查询目的的。
select a.*,b.score as ‘语文’,c.score as ‘数学’ from student a
inner join stu_sco b on a.s_id=b.s_id and c_id =‘01’
inner join stu_sco c on b.s_id=c.s_id and c.c_id =‘02’
where b.score>c.score;

######################################################################################################################################################
#–2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
– 修改一下上面的代码即可
select a.*,c.c_id,c.score from student a left join
(select a.s_id from (select s_id,c_id,score as score_01 from stu_sco where c_id=‘01’) a
inner join
(select s_id,c_id,score as score_02 from stu_sco where c_id=‘02’)b
on a.s_id=b.s_id and a.score_01<b.score_02) b
on a.s_id=b.s_id
inner join stu_sco c on b.s_id=c.s_id;

######################################################################################################################################################
#–3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
– 从stu_sco就能查询出学生编号和对应的平均成绩
select s_id,avg(score) as avg_score from stu_sco group by s_id;
– 剩下的要查询出学生名字,上面查询结果已经有字段s_id,可以作为子查询结果当做一张表。而表student有字段s_id和s_name字段,将这两个表关联起来查询即可
select a.s_id,a.s_name,b.avg_score from student a inner join
(select s_id,avg(score) as avg_score from stu_sco group by s_id) b on
a.s_id=b.s_id and avg_score>=60;

######################################################################################################################################################
#–4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩
#修改一下上面的代码即可
select a.s_id,a.s_name,b.avg_score from student a inner join
(select s_id,avg(score) as avg_score from stu_sco group by s_id) b on
a.s_id=b.s_id and avg_score<60;

######################################################################################################################################################
#–5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
#要查询所有学生的信息,无论某些学生是否有选课,也不论选课之后是否有考试成绩,都要查询出来,因此可以以student为主表,再左连接到stu_sco表即可。
select a.s_id as ‘学生编号’,a.s_name as ‘学生姓名’,count(b.c_id) as ‘选课总数’,sum(b.score) as ‘课程总成绩’
from student a left join stu_sco b on a.s_id=b.s_id group by a.s_id;

######################################################################################################################################################
#–6、查询"李"姓老师的数量
select count(t_id) as ‘李姓老师数量’ from teacher where t_name like ‘李%’;

######################################################################################################################################################
#–7、查询学过"张三"老师授课的同学的信息
#首先应该查询出张三老师授过哪些课以及对应的课程编码,最重要的是查询出张三老师的授课课程编码,作为下一步思考的子查询结果:
select b.c_id from teacher a inner join course b on a.t_id=b.t_id and a.t_name=‘张三’;
#又或者:
select b.c_id from teacher a , course b where a.t_id=b.t_id and a.t_name=‘张三’;
#同学的信息都在student表,想要知道哪些同学在上02的课(上面的查询结果),内连接到stu_sco表时,在on子句加上c_id='02’即可,只不过将’02’替换成子循环。
select a.*,b.c_id from student a inner join stu_sco b
on a.s_id=b.s_id and b.c_id=(select b.c_id from teacher a , course b where a.t_id=b.t_id and a.t_name=‘张三’);

######################################################################################################################################################
#–8、查询没学过"张三"老师授课的同学的信息
#修改一下上面的代码即可
select a.*,b.c_id from student a inner join stu_sco b
on a.s_id=b.s_id and b.c_id in (select b.c_id from teacher a , course b where a.t_id=b.t_id and a.t_name!=‘张三’);

######################################################################################################################################################
#–9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

最为简单直接的方法是从学过’01’的学生中挑选出学过’02’的学生,查询目标是学生的id,此时只使用stu_sco表即可,这时主要使用的知识点是关联子查询:

select s_id from stu_sco a where (select s_id from stu_sco b where a.s_id=b.s_id and b.c_id=‘01’ and a.c_id=‘02’);
#上面查询出同时学01和02课程的学生的id,既然学生id有了,将上面的查询语句作为子查询,下一步将student关联起来查询即可:
select * from student where s_id in
(select s_id from stu_sco a where (select s_id from stu_sco b where a.s_id=b.s_id and b.c_id=‘01’ and a.c_id=‘02’));

######################################################################################################################################################
#–10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

上一题是’01’和’02’课程都学的同学,所有学过’01’课程的同学减去上面那帮都学就是这题的答案,画一个文氏图马上就懂:

select s_id from student where s_id in
(select s_id from stu_sco a where (select s_id from stu_sco b where a.s_id=b.s_id and b.c_id=‘01’ and a.c_id=‘02’));
#上面查询结果是’01’和’02’课程都学的学生id,下面是学过’01’课程的学生id:
select s_id from stu_sco where c_id=‘01’;

第一个结果作为子查询,嵌套在第二个查询语句的where子句中即可:

select s_id from stu_sco where c_id=‘01’ and
s_id not in
(select s_id from student where s_id in
(select s_id from stu_sco a where (select s_id from stu_sco b where a.s_id=b.s_id and b.c_id=‘01’ and a.c_id=‘02’)));
#从上面就可以知道,id为06的学生是符合查询要求的,作为子查询结果,接下从student将这个学生的信息查询出来即可:
select * from student where s_id in
(select s_id from stu_sco where c_id=‘01’ and
s_id not in
(select s_id from student where s_id in
(select s_id from stu_sco a where (select s_id from stu_sco b where a.s_id=b.s_id and b.c_id=‘01’ and a.c_id=‘02’))));

######################################################################################################################################################
#-- 11、查询没有学全所有课程的同学的信息
#首先我们要想:到底有多少门课程,也就是说要查询出不重复课程的数量,如果一个学生所学习的课程数量等于这个数,
#就说明这名学生是学全了所有课程:
#第一步:求出不重复课程的数量
select count(distinct(c_id)) from course;
#第二步:数一下每个学生选了多少门课:
select s_id,count(c_id) from stu_sco group by s_id;
#第三步:上面那些学生,如果所选课程数量,比第一步的查询结果要少的,就是不学全课程的学生:
select a.s_id from (select s_id,count(c_id) as num from stu_sco group by s_id)a
where a.num<(select count(distinct(c_id)) from course);
#第四步:将上面那些学生的id和student表关联起来,就可以查询到这些学生的信息,因为我们要查的是这帮符合条件学生的信息,
#当然要以上面的查询结果为主表,左连接到student表:
select b.* from (select s_id,count(c_id) as num from stu_sco group by s_id)a
left join student b on a.s_id = b.s_id
where a.num<(select count(distinct(c_id)) from course);

######################################################################################################################################################
#–12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
#首先要查询出‘01’同学到底学了那些课程:
select c_id from stu_sco where s_id=‘01’;
#再查询出哪些同学学了以上课程,将上面的查询语句作为这次查询的where子句中的子查询即可:
select distinct(s_id) from stu_sco where c_id in (select c_id from stu_sco where s_id=‘01’);
#最后将上面那些学生id放在查询student表时的where子句之内即可,当然不要忘记排除01同学子句:
select * from student
where s_id in (select distinct(s_id) from stu_sco where c_id in (select c_id from stu_sco where s_id=‘01’))
and s_id!=‘01’;

######################################################################################################################################################
#–13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
#符合查询要求的学生要满足两个条件:
#一、01同学学的课程,他都学过
#二、01同学所学课程数量和他一致
#首先查出01同学学过那些课程:
select c_id from stu_sco where s_id=‘01’;

#将上面的查询结果和stu_sco关联起来,就可以查找哪些同学是都学过01同学学过的:
select a.c_id,b.s_id from (select c_id from stu_sco where s_id=‘01’)a inner join stu_sco b
on a.c_id=b.c_id;

上面的同学,有些是学过两门课,有些是学过三门课以上,和01同学所学的课程数不一致,要排除:

#01同学所学课程数量:
select count(c_id) from stu_sco where s_id=‘01’;
#上面的结果是3个,也就是说,要的那些同学,在stu_sco表中出现的次数要等于3次:
select s_id,count(s_id) from stu_sco group by s_id having count(s_id)=(select count(c_id) from stu_sco where s_id=‘01’);
#上面的这些同学的编号,作为新的子查询,内连接到前面的结果,就是要找的那些同学
select distinct(c.s_id) from (select a.c_id,b.s_id from (select c_id from stu_sco where s_id=‘01’)a inner join stu_sco b
on a.c_id=b.c_id)c inner join
(select s_id,count(s_id) from stu_sco group by s_id having count(s_id)=(select count(c_id) from stu_sco where s_id=‘01’))d
on c.s_id=d.s_id and c.s_id!=‘01’;
#当然,因为要查找的是同学的信息而不是单单是学号,所以还要左连到student,将这些学生的信息给查询出来
select distinct(c.s_id),e.s_name,e.s_age,e.s_sex from (select a.c_id,b.s_id from (select c_id from stu_sco where s_id=‘01’)a inner join stu_sco b
on a.c_id=b.c_id)c inner join
(select s_id,count(s_id) from stu_sco group by s_id having count(s_id)=(select count(c_id) from stu_sco where s_id=‘01’))d
on c.s_id=d.s_id and c.s_id!=‘01’
left join student e on d.s_id=e.s_id;

######################################################################################################################################################
#–14、查询没学过"张三"老师讲授的任一门课程的学生姓名
#首先查出张三老师授课的id
select a.c_id from course a inner join teacher b on a.t_id=b.t_id and t_name=‘张三’;
#再从stu_sco表中查询出学过上面课程id的学生(他们的编号)
select distinct(s_id) from stu_sco where c_id =
(select a.c_id from course a inner join teacher b on a.t_id=b.t_id and t_name=‘张三’);
#以上面的结果作为这次查询的where子句的条件,就能查询出没上过‘张三’老师课的学生名字
select * from student where s_id not in
(select distinct(s_id) from stu_sco where c_id =
(select a.c_id from course a inner join teacher b on a.t_id=b.t_id and t_name=‘张三’));

######################################################################################################################################################
#–15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
#首先查询出所有不及格的考试记录,统计曾经不及格的学生id:
select s_id,c_id,score from stu_sco where score<60;
#我们如果在上面的基础上,按照s_id分组,再查询一个聚合函数字段:
select s_id,c_id,count(s_id),score from stu_sco where score<60 group by s_id;
#从聚合函数count(s_id)中可以看到不及格次数,由于是分组之后查询,所以再用having方法筛选即可:
select s_id,c_id,count(s_id),score from stu_sco where score<60 group by s_id having count(s_id)>=2;
select s_id from stu_sco where score<60 group by s_id having count(s_id)>=2;
#从上面结果可以获得目标学员的id,还要查询姓名以及平均成绩,所以还需要用上面的结果左连接到student表和stu_sco表:
#(当然,既然要求平均成绩,最后还要按s_id作出分组)
select a.s_id,b.s_name,avg(c.score) as ‘平均成绩’ from
(select s_id from stu_sco where score<60 group by s_id having count(s_id)>=2)a
left join student b on a.s_id=b.s_id
left join stu_sco c on b.s_id=c.s_id
group by a.s_id;

######################################################################################################################################################
#----16、检索"01"课程分数小于60,按分数降序排列的学生信息
#首先查询出01课程分数小于60的学生id
select s_id ,score from stu_sco where c_id=‘01’ and score<60;
#还要查询学生的信息,因此需要左连到student表,同时以分数降序排列,
select b.*,a.score from
(select s_id ,score from stu_sco where c_id=‘01’ and score<60) a
left join student b on a.s_id=b.s_id
order by a.score desc;

######################################################################################################################################################
#–17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
#这题看着比较简单,但是因为既要显示学生所以的成绩,又要显示这些学生的平均成绩,还得排序,所以必须使用多表查询
#首先查询出第一个表:
select s_id,avg(score) from stu_sco group by s_id;
#重新查询stu_sco表所有字段,要将上面的avg(score)作为新的一个字段,添加到新的查询结果里面
#这时候就需要以stu_sco为主表,左连接到上面的查询结果中:
select a.*,b.avg_sco from stu_sco a left join
(select s_id,avg(score) as avg_sco from stu_sco group by s_id)b
on a.s_id=b.s_id
order by b.avg_sco desc;

######################################################################################################################################################
#–18、查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
#–及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
#所有的这些要查询的信息,都可以从stu_sco表中查询到,上面的各种区间的查询,可以先用case when 语句对所有成绩进行分箱标记:
select * ,
case when score>=60 then 1 else 0 end as pass,
case when score>=70 and score<80 then 1 else 0 end as medi,
case when score>=80 and score<90 then 1 else 0 end as good,
case when score>=90 then 1 else 0 end as excellent
from stu_sco;
#以上面查询结果作为子查询表,可以统计出目标查询结果,由于还需要查询出课程名,所以还需要做一次对course的多表查询:
#最后记得以c_id为分组字段即可
select a.c_id as ‘课程ID’,b.c_name as ‘课程name’,max(a.score) as ‘最高分’,min(a.score) as ‘最低分’,
avg(a.score) as ‘平均分’,sum(a.pass)/count(a.c_id) as ‘及格率’,
sum(a.medi)/count(a.c_id) as ‘中等率’,
sum(a.good)/count(a.c_id) as ‘优良率’,
sum(a.excellent)/count(a.c_id) as ‘优秀率’
from
(select * ,
case when score>=60 then 1 else 0 end as pass,
case when score>=70 and score<80 then 1 else 0 end as medi,
case when score>=80 and score<90 then 1 else 0 end as good,
case when score>=90 then 1 else 0 end as excellent
from stu_sco)a
left join course b on a.c_id=b.c_id
group by a.c_id;

######################################################################################################################################################
#–19、查询学生的总成绩并进行排名
#以下写法适用于MySQL5.7
set @rank:=0;
select a.*,@rank:=@rank+1 as rank from
(select s_id,sum(score) as ‘总成绩’ from stu_sco group by s_id order by sum(score) desc)a;

#如果要求用一个查询语句实现,不能多出其他语句,可以这样写:
#思路,将排名单独作为新的一张表(select @rank:=0)b
select a.*,@rank:=@rank+1 as rank from
(select s_id,sum(score) as ‘总成绩’ from stu_sco group by s_id order by sum(score) desc)a,
(select @rank:=0)b;

######################################################################################################################################################
#–20、按课程分类,用成绩对学生进行排名,排名升序
#思路
select c_id,s_id,score,rank from(
select a.c_id,a.s_id,a.score,if(@p=c_id,@r:=@r+1,@r:=1) as rank ,@p:=c_id
from stu_sco a, (select @p=Null,@r:=0)b
order by a.c_id,a.score desc)c;

######################################################################################################################################################
#–21、查询不同老师所教不同课程平均分从高到低显示
#很明显要
select a.t_id,a.t_name,b.c_name,avg(c.score) as’课程平均分’ from teacher a
left join course b on a.t_id=b.t_id
left join stu_sco c on b.c_id=c.c_id
group by a.t_id,b.c_name
order by avg(c.score) desc;

######################################################################################################################################################
#–22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

使用关联子查询的方法,具体看集训建议的例题:

#你可以使用以下查询查看第二名和第三名的学生id和课程id、成绩:
select a.s_id,a.c_id,a.score from stu_sco a where (select count(b.s_id) from stu_sco b where a.c_id=b.c_id and a.score< b.score)
between 1 and 3 group by a.c_id,a.s_id;
#因为还要查询学生的信息,所以上面的查询结果还需要关联到student表
select d.*,c.c_id,c.score from (
select a.s_id,a.c_id,a.score from stu_sco a where (select count(b.s_id) from stu_sco b where a.c_id=b.c_id and a.score< b.score)
between 1 and 3 group by a.c_id,a.s_id) c left join
student d on c.s_id=d.s_id;

#######################################################################################################################################
#–23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
#一看到分段什么的,就要想起case when语句了
select c_id,
case when score between 0 and 60 then 1 else 0 end as ‘[0-60]所占百分比’,
case when score between 60 and 70 then 1 else 0 end as ‘[60-70]所占百分比’,
case when score between 70 and 85 then 1 else 0 end as ‘[70-85]所占百分比’,
case when score between 85 and 100 then 1 else 0 end as ‘[85-100]所占百分比’
from stu_sco;
#上面的查询可以得到每一条考试分数记录所属等级,我们可以使用聚合函数来将上面的1、0记录转化为百分比
select c_id,
sum(case when score between 0 and 60 then 1 else 0 end)/count(c_id) as ‘[0-60]所占百分比’,
sum(case when score between 60 and 70 then 1 else 0 end)/count(c_id) as ‘[60-70]所占百分比’,
sum(case when score between 70 and 85 then 1 else 0 end)/count(c_id) as ‘[70-85]所占百分比’,
sum(case when score between 85 and 100 then 1 else 0 end)/count(c_id) as ‘[85-100]所占百分比’
from stu_sco group by c_id;
#另外,由于还需要查询课程名称,所以还需要关联到course表查询课程名称字段:
select a.c_id,b.c_name,
sum(case when score between 0 and 60 then 1 else 0 end)/count(a.c_id) as ‘[0-60]所占百分比’,
sum(case when score between 60 and 70 then 1 else 0 end)/count(a.c_id) as ‘[60-70]所占百分比’,
sum(case when score between 70 and 85 then 1 else 0 end)/count(a.c_id) as ‘[70-85]所占百分比’,
sum(case when score between 85 and 100 then 1 else 0 end)/count(a.c_id) as ‘[85-100]所占百分比’
from stu_sco a left join course b on a.c_id=b.c_id
group by c_id;

#######################################################################################################################################
#–24、查询每个学生平均成绩及其名次
select s_id,avg_score,(@rank:=@rank+1)as rank from(
select s_id,avg(score) as avg_score from stu_sco group by s_id order by avg(score) desc)a
,(select @rank:=0)b;

#######################################################################################################################################
#–25、查询各科成绩前三名的记录
#明显使用关联子查询知识,详情看集训讲义
select a.c_id,a.s_id,a.score from stu_sco a
where (select count(b.s_id) from stu_sco b where a.c_id=b.c_id and a.score<b.score)❤️
group by a.c_id,a.s_id;

#######################################################################################################################################
#–26、查询每门课程被选修的学生数
select c_id,count(s_id) as ‘选修学生数’ from stu_sco group by c_id;

#######################################################################################################################################
#–27、查询出只有两门课程成绩的全部学生的学号和姓名
select s_id,s_name from student where s_id in (
select s_id from stu_sco group by s_id having count(s_id)=2);

#######################################################################################################################################
#–28、查询男生、女生人数
select count(s_sex) as ‘人数’ from student group by s_sex;

#######################################################################################################################################
#–29、查询名字中含有"风"字的学生信息
select * from student where s_name like ‘%风%’;

#######################################################################################################################################
#–30、查询同名同姓学生名单,并统计同名人数
select s_name,num-1 as ‘同名人数’ from (
select *,count(s_id) as num from student group by s_name)a
;

#######################################################################################################################################
#–31、查询1990年出生的学生名单
select s_name from student where year(s_age)=‘1990’;

#######################################################################################################################################
#–32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select c_id,avg(score) from stu_sco group by c_id order by avg(score) desc,c_id;

#######################################################################################################################################
#–33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
select a.s_id,b.s_name,avg(a.score) from stu_sco a left join student b on a.s_id=b.s_id
group by a.s_id having avg(a.score)>=85;

#########################################################################################################################
#–34、查询课程名称为"数学",且分数低于60的学生姓名和分数
#首先查出数学的课程id:
select c_id from course where c_name=‘数学’;
#上面的查询结果作为子查询,查询stu_sco表s_id和score字段,再外连到student表查询学生姓名:
select b.s_name,a.score from stu_sco a
left join student b on a.s_id=b.s_id
where a.c_id=(select c_id from course where c_name=‘数学’)
and a.score<60;

#########################################################################################################################
#–35、查询所有学生的课程及分数情况;
#考察用case when语句在表转换的使用:
select a.s_id,b.s_name,
case when c_id=(select c_id from course where c_name=‘数学’) then score end as ‘数学成绩’,
case when c_id=(select c_id from course where c_name=‘语文’) then score end as ‘语文成绩’,
case when c_id=(select c_id from course where c_name=‘英语’) then score end as ‘英语成绩’
from stu_sco a left join student b on a.s_id=b.s_id;
#如果你不用sum聚合函数就会上面的结果,因此要:
select a.s_id,b.s_name,
sum(case when c_id=(select c_id from course where c_name=‘数学’) then score end) as ‘数学成绩’,
sum(case when c_id=(select c_id from course where c_name=‘语文’) then score end) as ‘语文成绩’,
sum(case when c_id=(select c_id from course where c_name=‘英语’) then score end) as ‘英语成绩’
from stu_sco a left join student b on a.s_id=b.s_id
group by a.s_id;

#########################################################################################################################
#–36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数;
select c.s_name,b.c_name,a.score from
stu_sco a left join course b on a.c_id=b.c_id
left join student c on a.s_id=c.s_id
where (a.s_id,a.c_id) in (select s_id,c_id from stu_sco where score>70);

#########################################################################################################################
#–37、查询出现过学生考试不及格的课程
select distinct(a.c_id),b.c_name from stu_sco a,course b where a.c_id=b.c_id and a.score<60;

#########################################################################################################################
#–38、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名;
select a.s_id,b.s_name from stu_sco a
inner join student b on a.s_id=b.s_id
where a.c_id=‘01’ and a.score>80;

#########################################################################################################################
#–39、求每门课程的学生人数
select c_id,count(s_id) from stu_sco group by c_id;

#########################################################################################################################
#–40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
#首先查询出张三所授课的课程id
select c_id from teacher a ,course b where a.t_id=b.t_id and t_name=‘张三’ ;
#然后查找出考这些课程的学生中,成绩最高的,此时要记住张三的课可能不止一门,所以记得以课程分组
select s_id,c_id,max(score) as score from stu_sco where c_id in (
select c_id from teacher a ,course b where a.t_id=b.t_id and t_name=‘张三’)
group by c_id;
#查询出这些学生的信息,就需要外连到student表:
select a.*,b.score from student a inner join
(select s_id,c_id,max(score) as score from stu_sco where c_id in (
select c_id from teacher a ,course b where a.t_id=b.t_id and t_name=‘张三’)
group by c_id) b
on a.s_id=b.s_id;

#########################################################################################################################
#–41、查询课程不同、成绩相同的学生的学生编号、课程编号、学生成绩
#按照关联子查询思维,可以将成绩分为两组,一组是本课程学生成绩,另外一组是其余课程学生成绩
select a.s_id,a.c_id,a.score from stu_sco a where
(select count(a.s_id) from stu_sco b where a.c_id<>b.c_id and a.score=b.score)>1;

#########################################################################################################################
#–42、查询每门功成绩最好的前两名
#同样是使用关联子查询的方法,讲义中有几乎一模一样的例题讲解:
select a.c_id,a.s_id,a.score from stu_sco a where
(select count(a.s_id) from stu_sco b where a.c_id=b.c_id and a.score<b.score)<2
group by a.c_id,a.s_id;

#########################################################################################################################
#–43、统计每门课程的学生选修人数(超过5人的课程才统计)。
#要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select c_id,count(s_id) as ‘选修人数’ from stu_sco
group by c_id having count(s_id)>5
order by count(s_id) desc,c_id;

#########################################################################################################################
#–44、检索至少选修两门课程的学生学号
#也就是学生id在考试成绩的记录要大于等于两次
select s_id from stu_sco group by s_id having count(s_id)>=2;

#########################################################################################################################
#–45、查询选修了全部课程的学生信息
#全部课程有多少?
select count(distinct(c_id)) from course;
#也就是说,要查询出考试纪录出现次数要和上面的查询结果一致才行:
select * from student
where s_id in (select s_id from stu_sco group by s_id having count(s_id)=(
select count(distinct(c_id)) from course));

#########################################################################################################################
#–46、查询各学生的年龄
select s_id,s_name,(year(now())-year(s_age)) as ‘年龄’ from student;

#########################################################################################################################
#–47、查询本周过生日的学生
#看看如今是这周是周几(周日为0,周一为1,…):
select date_format(now(),’%w’);
#现在离下一周还有多少天?
select 7-date_format(now(),’%w’);
#下一周也就是从多少号开始?
select adddate(curdate(),7-date_format(now(),’%w’));
#这周从几号开始算?
select adddate(curdate(),-(date_format(now(),’%w’)));
#也就是说,如果学生的出生的月+日在上面的月日之间,就是本周生日的学生
select s_name,date_format(s_age,‘2019-%m-%d’) from student;

select s_name,s_age from student
where date_format(s_age,‘2019-%m-%d’) between adddate(curdate(),-(date_format(now(),’%w’)))
and adddate(curdate(),7-date_format(now(),’%w’));

#########################################################################################################################
#–48、查询下周过生日的学生
#下周从多少号开始?
select adddate(curdate(),7-date_format(now(),’%w’));
#下周几号结束?
select adddate(adddate(curdate(),7-date_format(now(),’%w’)),7);
#修改上一题代码可得:
select s_name,s_age from student
where date_format(s_age,‘2019-%m-%d’) between adddate(curdate(),7-date_format(now(),’%w’))
and adddate(adddate(curdate(),7-date_format(now(),’%w’)),7);

#########################################################################################################################
#–49、查询本月过生日的学生
#当前是几月?
select month(now());
select s_id,s_name from student where date_format(s_age,’%m’)=month(now());

#–50、查询下月过生日的学生
select s_id,s_name from student where date_format(s_age,’%m’)=month(now())+1;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值