student表的数据如下:
1)向学生表里添加数据
添加数据的sql
insert into student(student_id,name,date,sex) values('5' , '猴子' , '1989-01-01' , '男'); insert into student(student_id,name,date,sex) values('6' , '小猫' , '1990-12-21' , '女'); insert into student(student_id,name,date,sex) values('7' , '小小马' , '1991-12-21' , '男'); insert into student(student_id,name,date,sex) values('8' , '王思' , '1990-05-20' , '男');
2)成绩表(score)
添加数据的sql
insert into score(course_id,student_id,score) values('4' , '1' , 80); insert into score(course_id,student_id,score) values('4' , '2' , 90); insert into score(course_id,student_id,score) values('4' , '3' , 99); insert into score(course_id,student_id,score) values('5' , '1' , 60); insert into score(course_id,student_id,score) values('5' , '3' , 80);
3)课程表
添加数据的sql
insert into course(course_id,name,teacher_id) values('4' , '音乐' , '4'); insert into course(course_id,name,teacher_id) values('5' , '美术' , '6'); insert into course(course_id,name,teacher_id) values('6' , '体育' , '5');
4)教师表里添加数据
添加数据的sql
-- 教师表:添加数据 insert into teacher(teacher_id,name) values('4' , '新的'); insert into teacher(teacher_id,name) values('5' , '飞过'); -- 这里的教师姓名是空值(null) insert into teacher(teacher_id,name) values('6' , null);
-- 查询姓“猴”的学生名单 select * from student WHERE name like '猴%'; -- 查询姓名最后一个字是“猴”的学生 select * from student where name like '%猴'; -- 查询姓名中拥有“猴”的学生名单、 select * from student where name like '%猴%';
-- 查询课程编号为“2”的总成绩 select sum(score) from score where course_id=2 * 分析思路 select 查询结果 [总成绩:汇总函数sum] from 从哪张表中查找数据[成绩表score] where 查询条件 [课程号是2] */
-- 查询选了课程的学生人数 select count(distinct student_id) as studentNum from score /* 这个题目翻译成大白话就是:查询有多少人选了课程 select 学号,成绩表里学号有重复值需要去掉 from 从课程表查找score; (distinct 去重,如果不去重的话,同一个人选了多门课也会叠加上) */
-- 查询各科成绩最高和最低的分, 以如下的形式显示:课程号,最高分,最低分 select course_id, max(score),min(score) from score group by course_id /* 分析思路 select 查询结果 [课程ID:是课程号的别名,最高分:max(成绩) ,最低分:min(成绩)] from 从哪张表中查找数据 [成绩表score] where 查询条件 [没有] group by 分组 [各科成绩:也就是每门课程的成绩,需要按课程号分组]; */
-- 查询每门课程被选修的学生数 select course_id,count(student_id) from score group by course_id /* 分析思路 select 查询结果 [课程号,选修该课程的学生数:汇总函数count] from 从哪张表中查找数据 [成绩表score] where 查询条件 [没有] group by 分组 [每门课程:按课程号分组]; */
-- 查询男生、女生人数 select sex,count(sex) from student group by sex /* 分析思路 select 查询结果 [性别,对应性别的人数:汇总函数count] from 从哪张表中查找数据 [性别在学生表中,所以查找的是学生表student] where 查询条件 [没有] group by 分组 [男生、女生人数:按性别分组] having 对分组结果指定条件 [没有] order by 对查询结果排序[没有]; */
-- 查询平均成绩大于60分学生的学号和平均成绩 /* 题目翻译成大白话: 平均成绩:展开来说就是计算每个学生的平均成绩 这里涉及到“每个”就是要分组了 平均成绩大于60分,就是对分组结果指定条件 分析思路 select 查询结果 [学号,平均成绩:汇总函数avg(成绩)] from 从哪张表中查找数据 [成绩在成绩表中,所以查找的是成绩表score] where 查询条件 [没有] group by 分组 [平均成绩:先按学号分组,再计算平均成绩] having 对分组结果指定条件 [平均成绩大于60分] */ select student_id,avg(score) from score group by student_id having avg(score)>60
/* 翻译成大白话: 第1步,需要先计算出每个学生选修的课程数据,需要按学号分组 第2步,选修大于两门课程:也就是每个学生选修课程数目>2,对分组结果指定条件 分析思路 select 查询结果 [学号,每个学生选修课程数目:汇总函数count] from 从哪张表中查找数据 [课程的学生学号:课程表score] where 查询条件 [选修大于两门课程:需要先计算出每个学生选修了多少门课, 需要用分组,所以这里没有where子句] group by 分组 [每个学生选修课程数目:按学号分组,然后用汇总函数count计算每个学号都选修了多少门课] having 对分组结果指定条件 [至少选修两门课程:每个学生选修课程数目>2] */ -- 查询选修大于两门课程的学生学号 select student_id,count(course_id) from score group by student_id having count(course_id)>2
/* 翻译成大白话,问题解析: 1)查找出姓名相同的学生有谁,每个姓名相同学生的人数 查询结果:姓名,人数 条件:怎么算姓名相同?按姓名分组后人数大于等于2,因为同名的人数大于等于2 分析思路 select 查询结果 [姓名,人数:汇总函数count(*)] from 从哪张表中查找数据 [学生表student] where 查询条件 [没有] group by 分组 [姓名相同:按姓名分组] having 对分组结果指定条件 [姓名相同:count(*)>=2] order by 对查询结果排序[没有]; */ SELECT name,count(*) as personNum from student GROUP BY name having count(*)>=2
/* 分析思路 select 查询结果 [课程号][分数] from 从哪张表中查找数据 [成绩表score] where 查询条件 [成绩 <75] group by 分组 [没有] having 对分组结果指定条件 [没有] order by 对查询结果排序[课程号从大到小排列:降序desc]; */ select course_id,score from score where score < 75 order by course_id desc
/* 分析思路 select 查询结果 [课程号,平均成绩:汇总函数avg(成绩)] from 从哪张表中查找数据 [成绩表score] where 查询条件 [没有] group by 分组 [每门课程:按课程号分组] having 对分组结果指定条件 [没有] order by 对查询结果排序[按平均成绩升序排序:asc,平均成绩相同时,按课程号降序排列:desc]; */ select course_id,avg(score) as 平均成绩 from score group by course_id order by 平均成绩 asc, course_id desc
/* 分析思路 select 查询结果 [] from 从哪张表中查找数据 [成绩表score] where 查询条件 [课程编号为“4”且分数小于等于90] group by 分组 [没有] having 对分组结果指定条件 [] order by 对查询结果排序[查询结果按按分数降序排列]; */ select student_id,score from score where course_id = 4 and score<=90 ORDER BY score desc
要求输出课程号和选修人数,查询结果按人数降序排序,若人数相同,按课程号升序排序
/* 分析思路 select 查询结果 [要求输出课程号和选修人数] from 从哪张表中查找数据 [] where 查询条件 [] group by 分组 [每门课程:按课程号分组] having 对分组结果指定条件 [学生选修人数(超过2人的课程才统计):每门课程学生人数>2] order by 对查询结果排序[查询结果按人数降序排序,若人数相同,按课程号升序排序]; */ select course_id,count(student_id) as personNum from score group by course_id HAVING count(student_id)>2 ORDER BY personNum desc,course_id asc
/* 分析思路 先分解题目: 1)[不及格课程]限制条件 2)[同学的学号及其平均成绩],也就是每个学生的平均成绩,显示学号,平均成绩 分析过程: 第1步:先查询存在不及格课程的同学的id 第2步:对第一步查询得到的id进行分组,统计 1)不及格课程 2)[存在不及格课程]:课程数目>0 /* 第1步:得到存在不及格课程的同学的id select 查询结果 [学号] from 从哪张表中查找数据 [涉及到成绩:成绩表score] where 查询条件 [score<60] group by 分组 [每个学生的平均:按学号分组] having 对分组结果指定条件 [不合格的成绩的数量大于1] order by 对查询结果排序[没有]; */ select student_id from score where score<60 GROUP BY student_id HAVING count(score)>0 /* 第2步:对第一步查询得到的id进行分组,统计平均值 select 查询结果 [学号,平均成绩:汇总函数avg(成绩)] from 从哪张表中查找数据 [涉及到成绩:成绩表score] group by 分组 [每个学生的平均:按学号分组] having 对分组结果指定条件 [限制条件:学号 in 第一步出来的学号] */ select student_id,avg(score) as 平均成绩 from score group by student_id having student_id in ( select student_id from score where score<60 GROUP BY student_id HAVING count(score)>0 )
【知识点】子查询 1.翻译成大白话 1)查询结果:学生学号,姓名 2)查询条件:所有课程成绩 <= 80 的学生,需要从成绩表里查找,用到子查询 第1步,写子查询(所有课程成绩 <= 80 的学生(我们换一个角度来讲,就是不要存在成绩大于80的学生)) select 查询结果[学号] from 从哪张表中查找数据[成绩表:score] where 查询条件[成绩 < 80] group by 分组[没有] having 对分组结果指定条件[没有] order by 对查询结果排序[没有] limit 从查询结果中取出指定行[没有]; select student_id from score WHERE score>80 第2步,查询结果:学生学号,姓名,条件是对前面1步查到的学号取反 select 查询结果[学号,姓名] from 从哪张表中查找数据[学生表:student] where 查询条件[用到运算符in](这里的in 的前面可以是where也可以是having,两个随便一个都行) group by 分组[没有] having 对分组结果指定条件[没有] order by 对查询结果排序[没有] limit 从查询结果中取出指定行[没有]; */ select student_id,name from student where student_id not in ( select student_id from score WHERE score>80 )
select student_id,name from student where student_id not in ( select student_id from score GROUP BY student_id HAVING count(course_id)>(select count(course_id) from course) )
select student_id,name from student where student_id in ( select student_id from score GROUP BY student_id HAVING count(course_id)=4 )
/* 查找2000年前出生的学生名单 学生表中出生日期列的类型是date */ select student_id,name from student where year(date)<2000
select course_id,max(score) as 各科最大成绩,student_id from score group by course_id
select * from score as a where score=( SELECT max(score) from score as b where b.course_id=a.course_id );
这里特意改了一下课程“2”中其中的一个学生分数,发现有两个相同的最大分数也可以查得出来。
同样的使用关联子查询来实现
select * from score as a where score=( SELECT min(score) from score as b where b.course_id=a.course_id );
select * from score where course_id =1 ORDER BY score DESC LIMIT 2
(select * from score where course_id =1 ORDER BY score DESC LIMIT 2) union all (select * from score where course_id =2 ORDER BY score DESC LIMIT 2) union all (select * from score where course_id =3 ORDER BY score DESC LIMIT 2) union all (select * from score where course_id =4 ORDER BY score DESC LIMIT 2) union all (select * from score where course_id =5 ORDER BY score DESC LIMIT 2)
不过上面这样我感觉挺麻烦的,需要先知道有哪些课程编号,然后我想通过下面这种方式行不行,结果只返回了最大的两门课程的数据
select * from score where course_id in (select course_id from course) ORDER BY score DESC LIMIT 2
select s.student_id,s.`name`,count(sc.course_id) as 选课数,sum(sc.score) as 总成绩 from student s left join score sc on s.student_id=sc.student_id GROUP BY s.student_id
select s.student_id,s.`name`,AVG(sc.score) as 平均成绩 from student s left join score sc on s.student_id=sc.student_id GROUP BY s.student_id HAVING avg(sc.score)>70
两种查询的结果都一样 1. select s.student_id,s.`name`,c.course_id,c.`name` from student s,score sc,course c where s.student_id=sc.student_id and sc.course_id=c.course_id 2. SELECT s.student_id,s.`name`,c.course_id,c.`name` from student s INNER JOIN score sc on s.student_id=sc.student_id INNER JOIN course c on sc.course_id=c.course_id
注意!注意!注意! 我面试的时候,有做过相似要求的题 QAQ
select course_id, sum(case when score>=60 then 1 else 0 end) as "及格人数", sum(case when score< 60 then 1 else 0 end) as "不及格人数" from score GROUP BY course_id
select c.course_id,c.`name`, sum(case when score between 85 and 100 then 1 else 0 end) as '[100-85]', sum(case when score>=75 and score<85 then 1 else 0 end) as '(85-75]', sum(case when score>=60 and score<75 then 1 else 0 end) as '(75-60]', sum(case when score<60 then 1 else 0 end) as '[<60]' from score sc RIGHT JOIN course c on sc.course_id=c.course_id GROUP BY sc.course_id,c.`name`
RIGHT JOIN 右连接,不管course里面的数据在score有没有用到,都显示
select c.course_id,c.`name`, sum(case when score between 85 and 100 then 1 else 0 end) as '[100-85]', sum(case when score>=75 and score<85 then 1 else 0 end) as '(85-75]', sum(case when score>=60 and score<75 then 1 else 0 end) as '(75-60]', sum(case when score<60 then 1 else 0 end) as '[<60]' from score sc left JOIN course c on sc.course_id=c.course_id GROUP BY sc.course_id,c.`name`
left JOIN 左连接,以左边的为主,右边没有用到的不要
两种都可: select s.student_id,s.`name` from student s,score sc where s.student_id=sc.student_id and sc.course_id=4 and sc.score>80 select s.student_id,s.`name` from student s INNER JOIN score sc on s.student_id=sc.student_id where sc.course_id=4 and sc.score>80
下面是学生的成绩表(表名score,列名:学号、课程号、成绩)
使用sql实现将该表行转列为下面的表结构
//第1步,使用常量列输出目标表的结构 select student_id,'课程号1','课程号2','课程号3','课程号4','课程号5' from score;
//第2步,使用case表达式,替换常量列为对应的成绩 select student_id, (case course_id when 1 then score else 0 end)as '课程号1', (case course_id when 2 then score else 0 end)as '课程号2', (case course_id when 3 then score else 0 end)as '课程号3', (case course_id when 4 then score else 0 end)as '课程号4', (case course_id when 5 then score else 0 end)as '课程号5' from score ORDER BY student_id asc //在这个查询结果中,每一行表示了某个学生某一门课程的成绩。 //比如第一行是'学号1'选修'课程号1'的成绩,而其他两列的'课程号2、3、4、5'成绩为0。 //如下方图所示
//第三步,分组 ,并使用最大值函数max取出下图学生每一个课程的最大值 select student_id, max(case course_id when 1 then score else 0 end)as '课程号1', max(case course_id when 2 then score else 0 end)as '课程号2', max(case course_id when 3 then score else 0 end)as '课程号3' from score GROUP BY student_id
参考:https://blog.csdn.net/u010565545/article/details/100785261/