创建表
create table if not exists student ( sid int(10) comment '学生学号', sname varchar(5) comment '学生姓名', sage datetime comment '学生出生日期', sgender char(1) comment '学生性别' )engine=innodb default charset=utf8; insert into student values (01,'赵雷','1990-01-01','男'); insert into student values (02,'钱电','1990-12-21','男'), (03,'孙风','1990-12-20','男'), (04,'李云','1990-12-06','男'), (05,'周梅','1991-12-01','女'), (06,'吴兰','1992-01-01','女'), (07,'郑竹','1989-01-01','女'), (08,'张三','2017-12-20','女'), (09,'李四','2017-12-25','女'), (10,'李四','2012-06-06','女'), (11,'赵六','2013-06-13','女'), (12,'孙七','2014-06-01','女'); -- 科目表 create table course ( cid int(10) comment '科目号', cname varchar(10) comment '科目名称', tid int(10) comment '授课老师' )engine=innodb default charset=utf8; insert into course values (01,'语文',02),(02,'数学',01),(03,'英语',03); --教师表 create table teacher( tid int(10) comment '教师学号', tname varchar(10) comment '教师姓名' )engine=innodb default charset=utf8; insert into teacher values(01,'张三'),(02,'李四'),(03,'王五'); --考试成绩表 create table score( sid int(10) comment '学生学号', cid int(10) comment '科目号', grade decimal(18,1) )engine=innodb default charset=utf8; insert into score values (01,01,80), (01,02,90), (01,03,99), (02,01,70), (02,02,60), (02,03,80), (03,01,90), (03,02,80), (03,03,80), (04,01,50), (04,02,30), (05,01,76), (05,02,87), (06,01,31), (06,03,34), (07,02,89), (07,03,98);Q1.1:查询同时存在01课程和02课程的情况
select * from (select * from score where score.cid=01) a, (select * from score where score.cid=02) b where a.sid=b.sid;Q1.2:查询存在01课程可能但可能不存在02课程的情况
select * from (select * from score where score.cid=01) a left join (select * from score where score.cid=02) b on a.sid=b.sid;Q1.3:查询不存在01但存在02的课程的情况
select * from score where score.sid not in( select sid from score where score.cid=01 ) and score.cid=02;Q4.1:查有成绩的学生信息
select s.sid,sname,sage,sgender from student s,( select distinct sid from score ) r where s.sid=r.sid;思路:① 从score表中,查询sid=01的学生所有的选课cid
② 从score表中,查询所有学生的sid,如果这个学生的cid出现在前面的结果中
③ 从student表中,查询所有学生的信息,如果这个学生的sid出现在前面的结果中
select * from student where sid in( select distinct sid from score where cid in( select cid from score where sid=01 ) );思路:满足2个条件
没有学01号同学没有学的课程 select sid from score where cid in( select cid from score where sid=01 ) group by sid 和01号同学学的课程数量相同 select sid from score group by sid having count(cid)=( select count(cid) from score where sid=01 )在student表中,查询所有学生的信息,如果这个学生的sid满足上面2个条件(即sid出现在前面两个的结果中)
select * from student where sid in( select sid from score where cid in( select cid from score where sid=01 ) group by sid ) and sid in( select sid from score group by sid having count(cid)=( select count(cid) from score where sid=01 ) )思路:① 在teacher表中,查询张三老师的tid
② 在course表中,查询科目cid,如果这个科目的tid出现在前面的结果中
③ 在score表中,查询学生sid,如果这个学生的cid出现在之前的结果中
④ 在student表中,查询学生信息,如果学生的sid不出现在前面的结果中
-- 方法1:嵌套查询 select * from student where sid not in( select sid from score where cid in( select cid from course where tid in( select tid from teacher where tname='张三' ) ) ); -- 方法2:多表联合查询 select * from student where sid not in( select sid from score,course,teacher where teacher.tname='张三' and teacher.tid=course.tid and score.cid=course.cid );思路:① 在score表中,选择grade<60,并group by sid,having count(cid)>1
② 在student表中,查询sname
select s.sid,sname,avg_grade from student s inner join ( select sid, avg(grade) as avg_grade from score where grade<60 group by sid having count(cid)>1 ) r on s.sid=r.sid思路:① 在score中,查询sid,avg(grade)
② score表和上表联合查询
select score.sid,grade,avg_grade from score left join( select sid,avg(grade) as avg_grade from score group by sid ) r on score.sid=r.sid order by avg_grade descQ14.1:将各科的科目名称、选课人数也查询出来
select r.*,cname from course c inner join ( select cid, max(grade) as 最高分, min(grade) as 最低分, avg(grade) as 平均分, count(sid) as 选课人数 from score group by cid ) r on c.cid=r.cid;不会,只能根据cid值来进行排序
set @rank=0; select cid,sid,grade,@rank:=@rank+1 as 排名 from ( select cid,sid,grade from score where cid=01 order by grade desc ) r;网上找到另外的一个答案如下:但是看不懂
select a.cid, a.sid, a.grade, count(b.grade)+1 as rank from score as a left join score as b on a.grade<b.grade and a.cid = b.cid group by a.cid, a.sid,a.grade order by a.cid, rank ASC;不会,只能做出一部分。以下代码从score表中按照cid将每一个学生的成绩从高到底进行了排序
select cid,sid,grade from score group by cid,sid order by cid,grade desc网上看到一种解法:使用partiton by函数
-- partition by cid order by grade desc:按照cid将每一个grade进行排序,然后选取其中的前三个 -- 但是注意:只能在mysql8.0以上版本才支持partition by的写法 select * from ( select *,row_number() over(partition by cid order by grade desc) as rank from score ) r where rank<4思路:① 在score表中,查找只选择了2门课的学生sid
② 在student表中,查找学生的sname,如果学生的sid在前面的结果中、
select sid,sname from student where sid in( select sid from score group by sid having count(cid)=2 );思路:① 在score表中,查询平均分大于85的学生sid,平均成绩
② 在student表中,查询sname
嵌套查询
select s.sid,sname,平均成绩 from student s inner join ( select sid,avg(grade) as 平均成绩 from score group by sid having 平均成绩>=85 ) r on s.sid=r.sid;连表查询
select a.sid,sname,avg(grade) as 平均成绩 from student a, score b where a.sid=b.sid group by b.sid having 平均成绩>=85;思路:① 在course表中,查询【数学】的cid
② 在score表中,查询分数低于60的sid,如果cid在前面的结果中
③ 连表查询sname
select sname,grade from student s inner join ( select sid,grade from score where cid in ( select cid from course where cname='数学' ) and grade<60 ) r on s.sid=r.sid;思路:① 在teacher表中,查询【张三】老师的tid
② 在course表中,根据tid查询cid
③ 在score表中,根据cid查询所有学生的成绩,然后按照成绩降序排序,最后选择第一条记录,就是第一名
select student.sid,sname,grade from student,score where cid=( select cid from course where tid=( select tid from teacher where tname='张三' ) ) and student.sid=score.sid order by grade desc limit 1;思路:前面已经找到了最高记录的分数grade,那么只要在score表中,查询所有的grade等于这个最高分的学生信息就可以了
为了查询结果,先修改表
update score set grade=90 where sid=07 and cid=02;查询:先查询最高是分数,然后在查询等于这个最高分数的学生信息
select a.sid,sname,grade from student a,teacher b,course c,score d where b.tname='张三' and b.tid=c.tid and c.cid=d.cid and d.sid=a.sid and d.grade=( select max(grade) from student,teacher,course,score where teacher.tname='张三' and teacher.tid=course.tid and course.cid=score.cid and score.sid=student.sid );与Q18相同,网上找到一种解答方案,但是看不懂
select a.sid,a.cid,a.grade from score as a left join score as b on a.cid = b.cid and a.grade<b.grade group by a.cid, a.sid having count(b.cid)<2 order by a.cid;思路:① 查询course表,统计一共有几门课
② 从score表中,查询选修了全部课程的学生sid
③ 从student表中,查询学生信息,如果这个学生的sid出现在前面的结果中
select * from student where sid in( select sid from score group by sid having count(cid)=( select count(cid) from course ) )补充一个知识点:mysql中日期范围搜索的三种方式
方式一:between and语句
select * from student where sage between '2018-01-01' and '2018-12-31';以上语句查询的实际时间范围是:2018-01-01 00:00:00 ~ 2018-12-31 00:00:00,而2018-12-31这一天的数据无法显示
方式二:datediff函数
语法:datediff(date1,date2) 该函数是返回两个日期之间的天数
select datadiff('2018-01-01','2018-01-05'); -- 结果:-4方式三:timestampdiff函数
语法:timestampdiff (interval,datetime1,datetime2),比较的单位interval可以为以下数值
该函数按照interval计算datetime2和datetime1之间的差值
FRAC_SECOND 表示间隔是毫秒 SECOND 秒 MINUTE 分钟 HOUR 小时 DAY 天 WEEK 星期 MONTH 月 QUARTER 季度 YEAR 年 select timestampdiff(day,'2018-07-01 09:00:00','2018-07-04 12:00:00'); -- 结果:3 select timestampdiff(Year,'2018-07-01 09:00:00','2019-01-04 12:00:00'); -- 结果:0CURDATE() 函数:返回当前的日期。
一般采用的是41中的:按照出生日期来算
思路:只要计算sage和当前日前之间差多少年即可
select sid,sname,timestampdiff(year,sage,curdate()) as 学生年纪 from student;weekofyear(datetime):计算datatime所在的周数
select weekofyear('2020-01-09'); -- 结果:2 -- 1月9号在2020年的第二周内思路:学生sage所在的周数与当前日期所在的周数,如果相等,就说明这个学生在这周过生日
select * from student where weekofyear(sage)=weekofyear(curdate());month(datatime):查询datatime所在的月份
select * from student where month(sage)=month(curdate());