Mysql 入门 50题目解析
Mysql 入门 50题目解析
# 表结构
# Student Course Teacher Score
# 学生表 课程表 教师表 成绩表
# 学生ID 主键 s_id 课程ID 主键 c_id 教师ID 主键 t_id 学生ID 主键 s_id
# 学生姓名 s_name 课程名字 c_name 教师姓名 t_name 课程ID c_id
# 学生生日 s_birth 课程教师ID t_id 课程分数 s_score
# 学生性别 s_sex
use test;
show tables;
show table status;
select * from student;
select * from Course;
select * from teacher;
select * from score;
alter table score;
# 1 查询"01"课程比"02"课程成绩高的学生的信息及课程分数
# 思路:
# 1.1 查询所有选修01和02的课程的学生
select s_id, score from sc where sc.c_id='01';
select s_id, s_score from score where score.c_id='01'; # as t01
select s_id, s_score from score where score.c_id='02'; # as t02
# 1.2 选出01课程02的课程比02课程分数高的学生ID
select t1.s_id,t2.s_id, t1.s_score, t2.s_score from (
(select s_id, s_score from score where score.c_id='01') as t1,
(select s_id, s_score from score where score.c_id='02') as t2
)
where t1.s_id = t2.s_id and t1.s_score > t2.s_score;
# 1.3 使用join关联学生信息表,查询出所有学生信息
select * from student right join( #右连接
select t1.s_id, class1, class2 from (
(select s_id, s_score as class1 from score where score.c_id='01') as t1,
(select s_id, s_score as class2 from score where score.c_id='02') as t2
)
where t1.s_id = t2.s_id and t1.class1 > t2.class2
) as r # 01课程比01课程分数多的学生的id 以及课程分数
on student.s_id = r.s_id;
# 2 查询同时在01和02课程的学生 条件查询
# 2.1 直接借鉴上一题目
select * from
(select * from score where score.s_id = '01') as t01,
(select * from score where score.s_id = '02') as t02
where t01.s_id = t02.s_id;
# 3 查询学生课程 有01 但是不一定有02 不存在为null
select * from
(select * from score where score.s_id = '01') as t01
left join
(select * from score where score.s_id = '02') as t02
on t01.s_id = t02.s_id;
# 4 查询学生没学过" 01 "课程但学过" 02 "课程的情况
# 4.1 查询出学习01课程的学生
# 4.2 以4.1为条件进行过滤查询
# 4.1 code
select s_id from score where score.s_id = '01';
# 4.2 code
select * from score
where score.s_id
not in(select s_id from score where score.s_id = '01')
and score.s_id = '02';
# 5 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
# 5.1 在 score分数表中使用id分组 对分组数据avg求均值
# 5.2 使用join 对score表 以及student表进行关联查询 筛选出id name avg-score
# 5.1 code
select s_id, avg(s_score) as avgss
from score
group by s_id
having avg(s_score) >60;
# 5.2
select student.s_id, student.s_name, scoreavg.avgss from
student right join (
select s_id, avg(s_score) as avgss
from score
group by s_id
having avg(s_score) >60) as scoreavg on student.s_id = scoreavg.s_id;
# 6 查询score表中存在成绩的学生信息
# distinct 区分 进行唯一查询
# 也可以使用关联查询,但是比较麻烦
select distinct student.* from student, score where student.s_id = score.s_id;
# 7 查询所学生的编号,姓名,选课总数,所有课程成绩的总成绩
# 7.1 所有课程成绩的总和,需要group by 分组 求和
# 7.2 需要所有的学生信息,需要join 连接student表
# 7.1
select s_id, sum(score.s_score) from score group by score.s_id having sum(score.s_score);
# 7.2
select
student_info.s_id,
student_info.s_name,
count(score_info.c_id) as sum_course,
sum(score_info.s_score) as sum_score
from
student as student_info
left join score as score_info on student_info.s_id = score_info.s_id
group by
student_info.s_id;
# 8 查询 所有姓李的老师的数量
# 8.1 使用 like % 模糊匹配
select count(teacher.t_id) from teacher where teacher.t_name like '李%';
# 9 查询学过 张三 老师课程的学生的信息
# 9.1 在teacher 表 找到 张三 老师的id
# 9.2 在course 表 找到所有张三老师的课程ID
# 9.3 在score表和student表中联以课程ID 为条件进行联合查询
# 9.1
select t_id from teacher where t_name = '张三';
# 9.2
select c_id from course where course.t_id = (select t_id from teacher where t_name = '张三');
# 9.3
select *
from
student as student_info join score as score_info on student_info.s_id = score_info.s_id
where
score_info.c_id in
(select c_id
from
course
where course.t_id = (select t_id from teacher where t_name = '张三'));
# 9 方法二
select
student.*, score.c_id
from
student, teacher, course, score
where
student.s_id = score.s_id
and
course.c_id = score.c_id
and
course.t_id = teacher.t_id
and
t_name = '张三';
# 10 查询没学过 张三老师课程的学生的信息
# 同上 使用 not in
# 方法 1
select *
from
student as student_info join score as score_info on student_info.s_id = score_info.s_id
where
score_info.c_id not in
(select c_id
from
course
where course.t_id = (select t_id from teacher where t_name = '张三'));
# 方法 2
select
student.*, score.c_id
from
student, teacher, course, score
where
student.s_id = score.s_id
and
course.c_id = score.c_id
and
course.t_id = teacher.t_id
and
t_name != '张三';
# 11 查询没有学全所有课程的学生
# 反向思维,有学全的就有没有学全的 (漏洞 可能都没有学全)
# 或者
# 在course表中count 课程数
# 在score表中group by student id count 课程数 小于所有课程数的就是没有学全的
# 方法 1 查找出学全的课程的学生ID
select score.s_id, count(score.s_id) from score group by score.s_id having count(score.s_id) = (select count(course.c_id) from course);
# 方法 2
select student_info.* from student as student_info left join score as score_info on student_info.s_id = score_info.s_id
group by
student_info.s_id
having
count(score_info.c_id) < (select count(course.c_id) from course);
# 12 查询至少有一门课程 和 01号学生 所学的课程相同的学生的信息
# 1 从score表中查询 01号 学生所学所有课程的 c_id
# 2 从score表中查询涉及c_id 课程的所有学生的s_id
# 3 从student表中查询包含的s_id 的信息
# step 1
select score.c_id from score where score.s_id = '01';
# step 2
select score.s_id from score where score.c_id in (select score.c_id from score where score.s_id = '01');
# step 3
select
student.*
from
student
where
student.s_id
in
(select score.s_id from score where score.c_id in (select score.c_id from score where score.s_id = '01'));
# 13 查询所有和 01号 学生所学相同的课程的学生
# 1 从score表中group concat 出 01号的课程c_id
# 2 从score中group concat 所有学生的课程c_id
# 3 找出group concat 相同的 s_id
# 4 从student 中查询找到的s_id 信息
# 13.1 01 号学生 的课程
select score.s_id, group_concat(score.c_id) from score group by score.s_id having score.s_id = '01';
# (select score.s_id, group_concat(score.c_id) from score group by score.s_id having score.s_id = '01') as 01group_concat;
# 13.2 所有学生的课程
select score.s_id, group_concat(score.c_id) from score group by score.s_id;
# (select score.s_id, group_concat(score.c_id) from score group by score.s_id) as allgroup_concat
# 13.3 选出所有学生中group_concat c_id = group_concat 01 c_id 的s_id
select allgroup_concat.s_id
from
(select score.s_id, group_concat(score.c_id) as all_concat from score group by score.s_id) as allgroup_concat,
(select score.s_id, group_concat(score.c_id) as 01_concat from score group by score.s_id having score.s_id = '01') as 1_group_concat
where
allgroup_concat.all_concat = 1_group_concat.01_concat;
# 13.4 从student中选出3中的s_id的学生信息 并且排除掉01号本身
select * from student
where
student.s_id in
(
select allgroup_concat.s_id
from
(select score.s_id, group_concat(score.c_id) as all_concat from score group by score.s_id) as allgroup_concat,
(select score.s_id, group_concat(score.c_id) as 01_concat from score group by score.s_id having score.s_id = '01') as 1_group_concat
where
allgroup_concat.all_concat = 1_group_concat.01_concat
)
and
student.s_id != '01';
# 14 查询没有学过 张三老师 课程的学生信息
# 从teacher表中查询老师id
# 从course中通过teacherid找到courseid
# 从score中通过courseid找到student id
# 14.1
select teacher.t_id from teacher where teacher.t_name = '张三';
# 14.2
select course.c_id from course where course.t_id in (select teacher.t_id from teacher where teacher.t_name = '张三');
# 14.3
select score.s_id from score where score.c_id in
(select course.c_id from course where course.t_id in
(select teacher.t_id from teacher where teacher.t_name = '张三'));
# 14.4
select * from student where student.s_id in
(select score.s_id from score where score.c_id in
(select course.c_id from course where course.t_id in
(select teacher.t_id from teacher where teacher.t_name = '张三')));
# 15 查询两门机器以上不及格的学生的学号,姓名,平均成绩
# 从score中选出score小于60的
# group by s_id count score.s_score >1
# 15.1 # 在score表中选出成绩低于60的
select * from score where score.s_score < 60;
# 15.2 # 在score对选出成绩<60的进行分组, 这样才能统计低于60的科目有几科
select *, group_concat(score.s_score) from score where score.s_score < 60 group by score.s_id;
# 15.3 # 在score中对分组后的<60的进行计数
select *, group_concat(score.s_score)from score where score.s_score < 60 group by score.s_id having count(*) > 1;
# 15.4
select
student.s_id, student.s_name, avg(score.s_score), group_concat(score.s_score)
from
student, score
where
student.s_id = score.s_id
and
score.s_score < 60 group by score.s_id having count(*) > 1;
# 16 查询 01课程 分数小于60的学生 按照分数降序排列
# 16.1 在score中查询01课程小于60的学生
# 16.02 排序
# 16.01
select * from score where score.s_score < 60 and score.c_id = '01';
# 16.02
select * from score where score.s_score < 60 and score.c_id = '01' order by score.s_score desc;
# 17 所有学生的查询平均成绩按照降序排列 显示 所有课程成绩以及平均成绩
# 17.1 查出所有学生的平均成绩
select score.s_id, group_concat(score.s_score), avg(score.s_score) from score group by score.s_id;
# 17.2 内连接显示成绩
select * from score
left join
(select score.s_id, avg(score.s_score) as avgscore from score group by score.s_id) as group_score
on
score.s_id = group_score.s_id
order by
avgscore
desc;
# 18 查询各个课程的最高分最低分平均分 按照 课程ID 最高分 最低分 平均分 及格率 中等率 优良率 优秀率 排列
# 及格( >= 60) 中等(70-80) 优良率(80-90) 优秀率(>90)
# 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
# max min avg
select
score.s_id,
max(score.s_score) as '最高分',
min(score.s_score) as '最低分',
avg(score.s_score) as '平均分',
count(*) as '人数',
sum(case when score.s_score >= 60 then 1 else 0 end )/count(*) as '及格率',
sum(case when score.s_score >= 70 and score.s_score < 80 then 1 else 0 end )/count(*) as '中等率',
sum(case when score.s_score >= 80 and score.s_score < 90 then 1 else 0 end )/count(*) as '优良率',
sum(case when score.s_score >= 90 then 1 else 0 end )/count(*) as '优秀率'
from
score
group by
score.s_id
order by
count(*) desc,
score.c_id asc;
# 19 按照各个科目的成绩进行排序
# 20 查询学生的总成绩 并进行排名 总分重复的时候不保留名次
# 21 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
# 1 course表和score表 group by join 查询
select course.c_name, course.c_id,
sum(case when score.s_score <=100 and score.s_score>85 then 1 else 0 end) as '[100-85]',
sum(case when score.s_score <=100 and score.s_score>85 then 1 else 0 end) / count(*) as '%',
sum(case when score.s_score <=85 and score.s_score>70 then 1 else 0 end) as '[85-70]',
sum(case when score.s_score <=85 and score.s_score>70 then 1 else 0 end) / count(*) as '%',
sum(case when score.s_score <=70 and score.s_score>60 then 1 else 0 end) as '[70-60]',
sum(case when score.s_score <=70 and score.s_score>60 then 1 else 0 end) / count(*) as '%',
sum(case when score.s_score <=60 and score.s_score>0 then 1 else 0 end) as '[60-0]',
sum(case when score.s_score <=60 and score.s_score>0 then 1 else 0 end) / count(*) as '%'
from
score left join course
on
score.c_id = course.c_id
group by
score.c_id;
# 22 查询各个科目成绩的前三名的记录
# 22.1 进行自关联
# 22.2 当2表比1表大的 前3个记录
select
t1.s_id, t1.c_id, t1.s_score
from
score as t1 left join score as t2 on t1.c_id = t2.c_id and t1.s_score < t2.s_score
group by
t1.s_id, t1.c_id, t1.s_score having count(t2.s_id) < 3
order by
t1.c_id;
# 23 查询出只选修两门课程的学生学号和姓名
# 使用 嵌套查询
# 1 对score按照s id分组
# 2 联合student表进行查询
select student.s_id, student.s_name from student
where
student.s_id in
(select score.s_id from score group by score.s_id having count(score.c_id) = 2);
# 24 查询男生人数
# group by 分组查询
select student.s_sex, count(student.s_sex) from student group by student.s_sex;
# 25 .查询同名学生名单,并统计同名人数
# 按照名字进行group by 找到同名的名字并统计个数
select student.s_name, count(student.s_name) from student group by student.s_name having count(*)>1;
# 26 查询 1990 年出生的学生名单
# 简单条件查询
select * from student where year(student.s_birth) = 1990;
# 27 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select score.s_id, course.c_name, avg(score.s_score) as avgscore from score, course where score.c_id = course.c_id group by score.c_id order by avgscore desc, course.c_id asc;
# 28 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
# 1 在score表中 group by s id 找到avg > 70 的 s id
select *, group_concat(score.s_score), avg(score.s_score) from score group by score.s_id having avg(score.s_score) >85;
# 2 嵌套查询
select
* #student.*, avg(score.s_score) as avgscore
from
score, student
where
score.s_id = student.s_id
group by
score.s_id
having
avg(score.s_score) > 85;
# 29 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
# 条件查询
select * from score, student, course where student.s_id = score.s_id and course.c_id = score.c_id and score.s_score < 60;
# 30 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
# 左连接查询 链接 student score
select * from student left join score on student.s_id = score.s_id;
# 31 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
# 多表查询
select * from student, course, score where student.s_id = score.s_id and score.c_id = course.c_id and score.s_score > 70;
# 32 查询存在不及格的课程ID
# group by 来取唯一,也可以用distinct
select * from score where score.s_score < 60 group by score.c_id;
# 33 查询课程编号为 01 且课程成绩在 80 分及以上的学生的学号和姓名
# 多条件查询
select * from score, student where score.s_id = student.s_id and score.s_score >= 80 and score.c_id = '01';
# 34 求每门课程的学生人数
# 在score表中group by c_id
select *, count(score.s_id) from score group by score.c_id;
# 35 查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩 (成绩不重复的时候)
# 涉及表 course teacher score student
select * from teacher, course, score, student
where
teacher.t_id = course.t_id
and
course.c_id = score.c_id
and
score.s_id = student.s_id
and
teacher.t_name ='张三'
order by
score.s_score desc limit 1;
# 36 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
# 内连接 链接条件即成绩相同 课程不同
# distinct 去重
select
distinct score_info1.s_id,score_info1.c_id,score_info1.s_score
from
score as score_info1, score as score_info2
where
score_info1.s_score = score_info2.s_score and score_info1.c_id != score_info2.c_id;
# 37 查询每门功成绩最好的前两名
# 内连接 通过每次的对比找出最大的前两条
select
*
from
score as score_info1 left join score as score_info2 on score_info1.c_id = score_info2.s_id and score_info1.s_score < score_info2.s_score
group by
score_info1.c_id, score_info2.c_id
having
count(score_info2.c_id) < 2
order by
score_info1.c_id;
# 统计每门课程的学生选修人数(超过 5 人的课程才统计)
select *, count(score.s_id) as countcid from score group by score.c_id having count(countcid) > 5;
# 38 查询至少选修两门课程的学生学号
# 对score group by sid
select distinct *, group_concat(score.c_id) from score group by score.s_id having count(score.c_id) >1;
# 39 查询选修了全部课程的学生信息
# distinct 出表course的课程
# 在score表中选出与课程数相同的sid
# 在student表中查询sid信息
select student.*
from
student, score
where
student.s_id = score.s_id
group by
score.s_id having count(score.c_id) = (select distinct count(*) from course);
# 40 查询各学生的年龄,只按年份来算
# timestampdiff 按照指定时间间隔计算指定日期到某个日趋的间隔时间
select student.*, (timestampdiff(year, student.s_birth, curdate())) from student;
# 41 查询本周过生日的学生
# 使用时间函数找出 和当前周相同的学生生日周
select student.* from student where weekofyear(student.s_birth) = weekofyear(curdate());
# 43 查询下周过生日的学生
# 使用时间函数找出和当下周(比当前周多一周)的学生生日周
select student.* from student where weekofyear(student.s_birth) = weekofyear(curdate()) + 1;
# 44 查询本月过生日的学生
# 原理同上 找出相同月
select * from student where month(student.s_birth) = month(curdate());
# 45 查询下月过生日的学生
# 原理同43
select * from student where month(student.s_birth) = month(curdate()) + 1;