文章目录
- 0. 数据表创建
- 1. 查询" 01 " 课程比 " 02 "课程成绩高的学生的信息及课程分数
- 2. 查询平均成绩大于等于60分的同学的学生编号和学生平均成绩
- 3. 查询在SC表存在成绩的学生信息
- 4. 查询所有同学的学生编号,学生姓名,选课总数,所有课程的总成绩(没成绩的显示为null)
- 5. 查询‘李’姓老师的数量
- 6.查询学过‘张三’老师授课的同学的信息
- 7. 查询没有学全所有课程的同学的信息
- 8. 查询至少一门课与学号为“01”的同学 所学相同的同学 的信息
- 9. 查询和“01”号同学学习的课程 完全相同 的其他同学的信息
- 10. 查询没学过“张三”老师讲授的任一们课程的学生姓名
- 11. 查询两门及以上不及格课程的同学的学号,姓名及其平均成绩
- 12. 检索“01”课程分数小于60,按分数降序排列的学生信息
- 13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
- 14. 查询各科成绩最高分,最低分和平均分
- 15. 按各科成绩进行排序,并显示排名,score重复时也继续排名
- 16. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺
- 17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
- 18. 查询各科成绩前三名的记录
- 19. 查询每门课程被选修的学生数
- 20. 查询出只选修两门课程的学生学号和姓名
- 21. 查询男生、女生人数
- 22. 查询名字中含有‘风’字的学生信息
- 23. 查询同名同性别学生名单,并统计同名同性别人数
- 24. 查询1990年出生的学生名单
- 25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
- 26. 查询平均成绩大于等于 85 的所有学生的学号,姓名和平均成绩
- 27. 查询课程名称为“数学”,且分数低于60的学生姓名和分数
- 28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
- 29.查询任何一门课程成绩在70分以上的姓名,课程名称和分数
- 30. 查询存在不及格的课程
- 31. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
- 32. 求每门课程的学生人数
- 33. 假设成绩不重复,查询选修“张三” 老师所授课程的学生中,成绩最高的学生信息及其成绩
- 34. 假设成绩有重复的情况下,查询选修‘张三’老师所授的学生中,成绩最高的学生信息及其成绩
- 35. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
- 36. 查询每门科目成绩最好的前两名
- 37. 统计每门课程的学生选修人数(超过5人的课程才统计)
- 38. 检索至少选修两门课程的学生学号
- 39. 查询选修了全部课程的学生信息
- 40. 查询各学生的年龄,只按年份计算
- 41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
- 42. 查询本周过生日的学生
- 43. 查询下周过生日的学生
- 44. 查询本周过生日的学生
- 45. 查询下月过生日的学生
0. 数据表创建
数据表关系图:
创建表SQL
语句
-- ---------- 建表语句-----------------
# 学生表 Student:
create table Student( SId varchar(10), Sname varchar(10), Sage datetime, Ssex varchar(10));
# 教师表 Teacher
create table Teacher(
TId varchar(10),
Tname varchar(10));
# 科目表 Course
create table Course(
CId varchar(10),
Cname nvarchar(10),
TId varchar(10));
# 成绩表 SC
create table SC(
SId varchar(10),
CId varchar(10),
score decimal(18,1));
-- ---------- 插入数据语句-----------------
# 学生表 Student:
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('09' , '张三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2017-12-30' , '女');
insert into Student values('12' , '赵六' , '2017-01-01' , '女');
insert into Student values('13' , '孙七' , '2018-01-01' , '女');
# 科目表 Course
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
# 教师表 Teacher
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
# 成绩表 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 "课程成绩高的学生的信息及课程分数
-- 1. 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
-- 思路
-- 关键词,“学生信息”,“课程分数”,“课程编号”
-- 1st, 锁定使用表,学生表,成绩表,这两张表提供所有的信息
-- 2nd, 通过SId主键连接学生和成绩表
SELECT
*
FROM student a
INNER JOIN sc b
ON a.SId = b.SId;
-- 3rd, 进行同一学生不同成绩的比较,那么就还需再连接一个成绩表,利用Sid相同,Cid不同进行关联。
SELECT
*
FROM student a
INNER JOIN sc b
ON a.SId = b.SId
INNER JOIN sc c
ON a.SId = c.SId AND b.CId='01' AND c.CId='02';
-- 4th, 筛选一下课程,利用where比较分数即可
SELECT
*
FROM student a
INNER JOIN sc b
ON a.SId = b.SId
INNER JOIN sc c
ON a.SId = c.SId AND b.CId='01' AND c.CId='02'
WHERE b.score > c.score;
1.1 查询同时存在 ‘01’ 课程和 '02’课程的情况
-- 1.1 查询同时存在" 01 "课程和" 02 "课程的情况
-- 思路
-- 关键词,“课程编号” 和 “同时存在”
-- 1st, 锁定所需表,成绩表SC
-- 2nd, 需要用到inner,
-- join, 实现1名学生的2门课程在同一行,左边的Cid='01'课程,右边的Cid='02'课程
SELECT
*
FROM (SELECT * FROM sc WHERE CId='01') a
INNER JOIN (SELECT * FROM sc WHERE CId='02') b
ON a.SId = b.SId;
-- 3rd, 简化,不用子查询
SELECT
*
FROM sc a
INNER JOIN sc b
ON a.SId = b.SId
WHERE a.CId = '01' AND b.CId = '02'
1.2 查询存在 ‘01’ 课程但可能不存在 ‘02’ 课程的情况(不存在时显示为 null )
-- 1.2 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
-- 思路
-- 关键词,“01”课程必须 和 “02”课程不必须
-- 1st, 锁定所需表,成绩表SC
-- 2nd, 需要用到left
-- join, 实现1名学生的2门课程在同一行,左边的Cid='01'课程,右边的Cid='02'课程
SELECT
*
FROM (SELECT * FROM sc WHERE CId='01')a
LEFT JOIN sc b
ON a.SId = b.CId AND b.CId='02';
-- 3rd, 简化,不用子查询
SELECT
*
FROM sc a
LEFT JOIN sc b
ON a.SId = b.SId AND b.CId='02'
WHERE a.CId='01';
1.3 查询不存在’01’课程但存在’02’课程的情况
-- 1.3 查询不存在" 01 "课程但存在" 02 "课程的情况
-- 思路
-- 关键词,“01”课程不存在 和 “02”课程存在,使用where语句
-- 1st, 锁定所需表,成绩表SC
-- 2nd, 筛选出存在‘01’情况
SELECT SId FROM sc WHERE CId='01';
-- 3rd, 使用not in筛选出不存在‘01’课程、但是存在‘02’课程的学生
SELECT
*
FROM sc
WHERE SId NOT IN (SELECT SId FROM sc WHERE CId='01') AND CId='02';
2. 查询平均成绩大于等于60分的同学的学生编号和学生平均成绩
-- 2. 查询平均成绩大于等于60分的同学的学生编号和学生平均成绩
-- 分析关键词,“学生编号”, “学生姓名”, “平均成绩>=60”
-- 1st, 锁定使用表,学生表,成绩表
-- 2nd, 成绩表按照Sid聚合,获取平均成绩,并且筛选出平均成绩>=60的Sid 和平均成绩
SELECT
sid, AVG(score) AS avg_score
FROM sc
GROUP BY Sid
HAVING avg_score >= 60;
-- 3rd, 利用inner join 连接学生表,获取学生姓名
SELECT
a.SId, a.Sname, avg_score -- 这里用 a 或 b 一样
FROM student a
INNER JOIN
(SELECT
sid, AVG(score) AS avg_score
FROM sc
GROUP BY Sid
HAVING avg_score >= 60) b
ON a.SId = b.SId;
3. 查询在SC表存在成绩的学生信息
-- 3. 查询在SC表存在成绩的学生信息
-- 关键词,“SC表”,“成绩”,“学生信息”
-- 1st, 锁定使用表,学生表,成绩表
-- 2nd, 以成绩表为主,左连接学生表,连接主键Sid,使用left join
SELECT
b.*
FROM sc a
LEFT JOIN student b
ON a.sid = b.sid;
-- 3rd, 使用group by, 从成绩表中取出唯一Sid,左连接学生表
SELECT
b.*
FROM (SELECT sid FROM sc GROUP BY SId) a -- 去重
LEFT JOIN student b
ON a.sid = b.sid;
4. 查询所有同学的学生编号,学生姓名,选课总数,所有课程的总成绩(没成绩的显示为null)
-- 4. 查询所有同学的学生编号,学生姓名,选课总数,所有课程的总成绩(没成绩的显示为null)
-- 关键词,“学生信息”,“选课总数”,“所有课程总成绩”
-- 1st, 锁定使用表,学生表,成绩表
-- 2nd, 在SC表中对Sid进行聚合,获取每个学生的选课总数,所有课程总成绩
SELECT
sid,
COUNT(CId) as ct,
SUM(score) as sum_score
FROM sc
GROUP BY Sid; -- 大小写无影响
-- 3rd, 学生表为主表,与第二步得到的成绩汇总表进行左连接
SELECT
a.SId, a.Sname, b.ct, b.sum_score
FROM Student a
LEFT JOIN
(SELECT
sid,
COUNT(CId) as ct,
SUM(score) as sum_score
FROM sc
GROUP BY Sid) b
ON a.SId = b.SId;
4.1 查询有成绩的学生信息
-- 4.1 查询有成绩的学生信息
-- 1st, 锁定使用表,学生表,成绩表
-- 2nd, 筛选出有成绩的Sid
SELECT SId FROM sc GROUP BY SId;
-- 3rd, 利用有成绩的Sid对student表做筛选
SELECT
*
FROM student
WHERE sid IN(SELECT SId FROM sc GROUP BY SId);
5. 查询‘李’姓老师的数量
-- 5. 查询‘李’姓老师的数量
-- 关键词,“老师”, “李”,“数量”
-- 1st, 锁定表,教师表
-- 2nd, 筛选出‘李’姓老师(提示:使用 like,% 代表占位符)
SELECT
*
FROM teacher
WHERE Tname LIKE '李%';
-- 统计‘李’姓老师的数量
SELECT
COUNT(*)
FROM teacher
WHERE Tname LIKE '李%';
6.查询学过‘张三’老师授课的同学的信息
-- 6.查询学过‘张三’老师授课的同学的信息
-- 关键词,“教师姓名”,“同学信息”
-- 1st, 锁定表,教师表,课程表,成绩表,学生表
-- 2nd,关联课程表和教师表,得到课程Cid与教师Tname的关系
SELECT a.*,Tname FROM course a INNER JOIN teacher b ON a.TId=b.TId;
-- 3rd, 与成绩表关联,得到学生Sid与教师Tname的关系
SELECT a.*,Tname FROM sc a
INNER JOIN (SELECT a.*,Tname FROM course a INNER JOIN teacher b ON a.TId=b.TId GROUP BY Tname) b
ON a.CId = b.cid;
-- 4th,与学生表关联,获取学生信息
SELECT a.*,Tname FROM student a
INNER JOIN (SELECT a.*,Tname FROM sc a
INNER JOIN (SELECT a.*,Tname FROM course a INNER JOIN teacher b ON a.TId=b.TId) b
ON a.CId = b.cid) b
ON a.SId = b.SId;
-- 5th, 增加筛选条件,Tname=‘张三’
SELECT a.*,Tname FROM student a
INNER JOIN (SELECT a.*,Tname FROM sc a
INNER JOIN (SELECT a.*,Tname FROM course a INNER JOIN teacher b ON a.TId=b.TId) b
ON a.CId = b.cid) b
ON a.SId = b.SId
WHERE Tname='张三';
7. 查询没有学全所有课程的同学的信息
-- 7. 查询没有学全所有课程的同学的信息
-- 关键词,“同学信息”,“所有课程”
-- 1st, 锁定表,学生表,成绩表,课程表
-- 2nd, 根据课程表,获取全部课程总数
SELECT COUNT(CId) FROM course;
-- 3rd, 根据成绩表,获取每个学生的所学课程总数,并筛选出所学课程总数小于全部课程总数的学生SId
SELECT
sid, COUNT(CId) as ct
FROM sc
GROUP BY SId
HAVING ct < (SELECT COUNT(CId) FROM course);
-- 4th, 关联学生表,获取学生信息
SELECT
a.*, ct
FROM student a
INNER JOIN
(SELECT
sid, COUNT(CId) as ct
FROM sc
GROUP BY SId
HAVING ct < (SELECT COUNT(CId) FROM course)) b
ON a.SId = b.SId;
8. 查询至少一门课与学号为“01”的同学 所学相同的同学 的信息
-- 8. 查询至少一门课与学号为“01”的同学 所学相同的同学 的信息
-- 关键词,“学生信息”, “课程”
-- 1st, 锁定表,成绩表,学生表
-- 2nd, 根据成绩表,获取“01”同学所学课程的编号
SELECT CId FROM sc WHERE SId='01';
-- 3rd, 使用in, 获取课程编号在“01”同学所学课程编号 范围内的记录
SELECT
*
FROM sc
WHERE CId in (SELECT CId FROM sc WHERE SId='01');
-- 4th, 关联学生表,获取学生信息
SELECT
DISTINCT a.* -- DISTINCT 去重
FROM student a
INNER JOIN
(SELECT
*
FROM sc
WHERE CId in (SELECT CId FROM sc WHERE SId='01')) b
ON a.SId = b.SId;
9. 查询和“01”号同学学习的课程 完全相同 的其他同学的信息
-- 9. 查询和“01”号同学学习的课程 完全相同 的其他同学的信息
-- 关键词,“学生信息”,“课程”,“完全相同”
-- “完全相同” 两层含义,1. 没有学习“01”号同学学习课程以外的其他课程;2. 与“01”号同学学习课程数量相等
-- 1st, 锁定表,学生表,成绩表
-- 2nd, 找出学了“01”号同学学习课程以外其他课程的同学
SELECT sid FROM sc WHERE CId not in (SELECT cid FROM sc WHERE SId='01');
-- 3rd, 排除第二步找到的同学以及“01”号同学
SELECT SId FROM sc
WHERE sid NOT IN (SELECT sid FROM sc WHERE CId not in (SELECT cid FROM sc WHERE SId='01')) AND SId != '01'
GROUP BY SId; # GROUP BY 这里去重
-- 4th, 筛选出与“01”号同学学习课程数量相等的同学
SELECT SId FROM sc
WHERE sid NOT IN (SELECT sid FROM sc WHERE CId not in (SELECT cid FROM sc WHERE SId='01')) AND SId != '01'
GROUP BY SId
HAVING COUNT(CId) = (SELECT COUNT(CId) FROM sc WHERE SId='01');
-- 5th, 关联学生表,获取学生信息
SELECT
b.*
FROM
(SELECT SId FROM sc
WHERE sid NOT IN (SELECT sid FROM sc WHERE CId not in (SELECT cid FROM sc WHERE SId='01')) AND SId != '01'
GROUP BY SId
HAVING COUNT(CId) = (SELECT COUNT(CId) FROM sc WHERE SId='01')) a
INNER JOIN student b
ON a.SId = b.SId;
10. 查询没学过“张三”老师讲授的任一们课程的学生姓名
-- 10. 查询没学过“张三”老师讲授的任一们课程的学生姓名
-- 关键词,“学生姓名”,“张三老师”
-- 1st, 锁定表,4张表
-- 2nd, 关联课程表和教师表,筛选出张三老师讲授课程的cid
SELECT * FROM course a INNER JOIN teacher b ON a.TId=b.TId WHERE Tname='张三';
-- 3rd, 关联成绩表,获取学过张三老师课程的sid
SELECT sid FROM sc a
LEFT JOIN course b
ON a.CId=b.CId
INNER JOIN teacher c
ON b.TId=c.TId
WHERE Tname='张三';
-- 4th, 关联学生表,使用not in, 筛选出没有学过“张三”老师课程的Sid
SELECT
Sname
FROM student a
WHERE SId NOT IN (SELECT sid FROM sc a
LEFT JOIN course b
ON a.CId=b.CId
INNER JOIN teacher c
ON b.TId=c.TId
WHERE Tname='张三');
11. 查询两门及以上不及格课程的同学的学号,姓名及其平均成绩
-- 11. 查询两门及以上不及格课程的同学的学号,姓名及其平均成绩
-- 关键词,“学号姓名”,“平均成绩”,“课程”
-- 1st, 锁定表,学生表,成绩表
-- 2nd, 求学生的平均成绩
SELECT SId, AVG(score) as avg_score FROM sc GROUP BY SId;
-- 3rd, 找出两门及以上不及格课程的同学
SELECT SId FROM sc
WHERE score < 60
GROUP BY SId
HAVING COUNT(CId) >= 2;
-- 4th, 结合第2和3步,求有两门及以上课不及格课程的同学的平均成绩
SELECT a.SId, AVG(score) as avg_score -- 这里两个表a,b 都有sid, 选择sid时要变为a.SId
FROM sc a
INNER JOIN (
SELECT SId FROM sc
WHERE score < 60
GROUP BY SId
HAVING COUNT(CId) >= 2) b
ON a.SId = b.SId
GROUP BY a.SId;
-- 5th, 关联学生表,获取学生学号
SELECT
a.SId, b.Sname, avg_score
FROM (SELECT a.SId, AVG(score) as avg_score
FROM sc a
INNER JOIN (
SELECT SId FROM sc
WHERE score < 60
GROUP BY SId
HAVING COUNT(CId) >= 2) b
ON a.SId = b.SId
GROUP BY a.SId) a
LEFT JOIN student b
ON a.SId=b.SId;
12. 检索“01”课程分数小于60,按分数降序排列的学生信息
-- 12. 检索“01”课程分数小于60,按分数降序排列的学生信息
-- 关键词,“学生信息”,“课程分数”,“降序”
-- 1st, 锁定表,学生表,成绩表
-- 2nd, 筛选“01”课程分数小于60的Sid
SELECT SId,score FROM sc WHERE CId='01' AND score<60;
-- 3rd, 关联学生表,获取学生信息,并按照分数降序排列
SELECT
b.*, a.score
FROM (SELECT SId,score FROM sc WHERE CId='01' AND score<60) a
LEFT JOIN student b
ON a.SId = b.SId
ORDER BY a.score DESC;
13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
-- 13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
-- 关键词, “所有学生”,“所有课程”,“平均成绩”
-- 1st, 锁定使用表,学生表,成绩表
-- 2nd, 获取所有学生的所有课程成绩(学生表左连接成绩表,没有成绩显示null)
SELECT
a.SId, b.CId, b.score
FROM student a
LEFT JOIN sc b
on a.SId = b.SId;
-- 3rd, 求学生平均成绩
SELECT
sid, AVG(score) as avg_score
FROM sc
GROUP BY sid;
-- 4th, 给每条成绩加上平均成绩,最终按照平均成绩降序排序
SELECT
a.SId, a.CId, a.score, avg_score
FROM (SELECT a.SId, b.CId, b.score FROM student a LEFT JOIN sc b on a.SId = b.SId) a
LEFT JOIN (SELECT sid, AVG(score) as avg_score FROM sc GROUP BY sid) b
ON a.SId = b.SId
ORDER BY b.avg_score DESC;
14. 查询各科成绩最高分,最低分和平均分
-- 14. 查询各科成绩最高分,最低分和平均分
-- 以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
-- 及格为:>=60, 中等:[70,80), 优良[80,90), 优秀>=90
-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
-- 分析题目:课程号、课程名称、聚合计算(选修人数、最高分、最低分,平均分,及格率,中等率,优良率,优秀率)、排序
-- 1st, 确定使用表,成绩表,课程表
-- 2nd, 聚合计算(使用条件判断语句 case when)
SELECT
CId,
COUNT(*) AS 选修人数,
MAX(score) AS 最高分,
MIN(score) AS 最低分,
AVG(score) AS 平均分,
SUM(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格率,
SUM(CASE WHEN score>=70 AND score<80 THEN 1 ELSE 0 END)/COUNT(*) AS 中等率,
SUM(CASE WHEN score>=80 AND score<90 THEN 1 ELSE 0 END)/COUNT(*) AS 良好率,
SUM(CASE WHEN score>=90 THEN 1 ELSE 0 END)/COUNT(*) AS 优秀率
FROM sc
GROUP BY CId;
-- 3rd, 排序(按照选修人数降序、课程号升序排列)
SELECT
CId,
COUNT(*) AS 选修人数,
MAX(score) AS 最高分,
MIN(score) AS 最低分,
AVG(score) AS 平均分,
SUM(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格率,
SUM(CASE WHEN score>=70 AND score<80 THEN 1 ELSE 0 END)/COUNT(*) AS 中等率,
SUM(CASE WHEN score>=80 AND score<90 THEN 1 ELSE 0 END)/COUNT(*) AS 良好率,
SUM(CASE WHEN score>=90 THEN 1 ELSE 0 END)/COUNT(*) AS 优秀率
FROM sc
GROUP BY CId
ORDER BY COUNT(*) DESC, CId ASC;
-- 4th, 关联课程表,获取cname
SELECT
a.*, Cname
FROM (SELECT
CId,
COUNT(*) AS 选修人数,
MAX(score) AS 最高分,
MIN(score) AS 最低分,
AVG(score) AS 平均分,
SUM(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格率,
SUM(CASE WHEN score>=70 AND score<80 THEN 1 ELSE 0 END)/COUNT(*) AS 中等率,
SUM(CASE WHEN score>=80 AND score<90 THEN 1 ELSE 0 END)/COUNT(*) AS 良好率,
SUM(CASE WHEN score>=90 THEN 1 ELSE 0 END)/COUNT(*) AS 优秀率
FROM sc
GROUP BY CId
ORDER BY COUNT(*) DESC, CId ASC) a
LEFT JOIN course b
ON a.CId = b.CId;
15. 按各科成绩进行排序,并显示排名,score重复时也继续排名
知识点:ROW_NUMBER()
,RANK()
, DENSE_RANK()
区别
-
ROW_NUMBER()
: 依次排序,不会出现相同排名 -
RANK()
: 出现相同排名时,跳跃排名 -
DENSE_RANK()
: 出现相同排名时,连续排名
-- 15. 按各科成绩进行排序,并显示排名,score重复时也继续排名
SELECT
*,
ROW_NUMBER() over (PARTITION by CId ORDER BY score DESC) AS 排名
FROM sc;
-- 15.1 按各科成绩进行排序,并显示排名,score 重复时合并名次
SELECT
*,
RANK() over (PARTITION by CId ORDER BY score DESC) AS 排名
FROM sc;
SELECT
*,
DENSE_RANK() over (PARTITION by CId ORDER BY score DESC) AS 排名
FROM sc;
16. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺
-- 16. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺
-- 关键词,“总分”,“保留名次空缺”
-- 1st, 计算总成绩
SELECT
SId, SUM(score) AS sum_score
FROM sc
GROUP BY SId;
-- 2nd, 按总成绩排名,排名跳跃
SELECT
*,
RANK() over (ORDER BY sum_score DESC) AS 排名
FROM (SELECT
SId, SUM(score) AS sum_score
FROM sc
GROUP BY SId) a;
-- 16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
-- 关键词,“总分”,“不保留名次空缺”
-- 1st, 计算总成绩
-- 2nd, 按总成绩排名,排名连续
SELECT
*,
DENSE_RANK() over (ORDER BY sum_score DESC) AS 排名
FROM (SELECT
SId, SUM(score) AS sum_score
FROM sc
GROUP BY SId) a;
17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
-- 17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
-- 关键词,“课程编号”, “课程名称”, “分数段”, “人数”
-- 1st, 锁定表,成绩表,课程表
-- 2nd, 使用case when, 按照课程编号统计各分数段人数
SELECT
CId,
SUM(case when score>=0 and score<60 then 1 else 0 END) as '[60-0]',
SUM(case when score>=60 and score<70 then 1 else 0 END) as '[70-60]',
SUM(case when score>=70 and score<85 then 1 else 0 END) as '[85-70]',
SUM(case when score>=85 and score<=100 then 1 else 0 END) as '[100-85]'
FROM sc
GROUP BY CId;
-- 3rd, 转化成所占百分比
SELECT
CId,
SUM(case when score>=0 and score<60 then 1 else 0 END)/COUNT(*) as '[60-0]',
SUM(case when score>=60 and score<70 then 1 else 0 END)/COUNT(*) as '[70-60]',
SUM(case when score>=70 and score<85 then 1 else 0 END)/COUNT(*) as '[85-70]',
SUM(case when score>=85 and score<=100 then 1 else 0 END)/COUNT(*) as '[100-85]'
FROM sc
GROUP BY CId;
-- 4th, 使用concat拼接,输出百分比符号
SELECT
CId,
CONCAT(SUM(case when score>=0 and score<60 then 1 else 0 END)/COUNT(*)*100, '%') as '[60-0]',
CONCAT(SUM(case when score>=60 and score<70 then 1 else 0 END)/COUNT(*)*100, '%') as '[70-60]',
CONCAT(SUM(case when score>=70 and score<85 then 1 else 0 END)/COUNT(*)*100, '%') as '[85-70]',
CONCAT(SUM(case when score>=85 and score<=100 then 1 else 0 END)/COUNT(*)*100, '%') as '[100-85]'
FROM sc
GROUP BY CId;
-- 5th, 关联课程表,输出课程名称
SELECT
a.*, b.Cname
FROM
(SELECT
CId,
CONCAT(SUM(case when score>=0 and score<60 then 1 else 0 END)/COUNT(*)*100, '%') as '[60-0]',
CONCAT(SUM(case when score>=60 and score<70 then 1 else 0 END)/COUNT(*)*100, '%') as '[70-60]',
CONCAT(SUM(case when score>=70 and score<85 then 1 else 0 END)/COUNT(*)*100, '%') as '[85-70]',
CONCAT(SUM(case when score>=85 and score<=100 then 1 else 0 END)/COUNT(*)*100, '%') as '[100-85]'
FROM sc
GROUP BY CId) a
LEFT JOIN course b
ON a.CId = b.CId;
18. 查询各科成绩前三名的记录
-- 18. 查询各科成绩前三名的记录
-- 关键词,“各科成绩”,“前三名”
-- 1st, 各科成绩排名
SELECT
*,
DENSE_RANK() over (PARTITION by CId ORDER BY score DESC) as score_rank -- PARTITION 分区
FROM sc;
-- 2nd, 筛选前三名
SELECT
*
FROM (SELECT
*,
DENSE_RANK() over (PARTITION by CId ORDER BY score DESC) as score_rank -- PARTITION 分区
FROM sc) a
WHERE score_rank <=3;
19. 查询每门课程被选修的学生数
-- 19. 查询每门课程被选修的学生数
-- 关键词,“每门课程”, “学生数”
-- 1st, 锁定表,成绩表
-- 2nd, 按照课程编号进行分组排序
SELECT
cid,
COUNT(*) AS 学生数
FROM sc
GROUP BY CId;
20. 查询出只选修两门课程的学生学号和姓名
-- 20. 查询出只选修两门课程的学生学号和姓名
-- 关键词,“两门课程”,“学生学号和姓名”
-- 1st, 锁定表,成绩表,学生表
-- 2nd, 统计每个学生选修课程数,并筛选出只选修2门课程的学生Sid
SELECT
sid,
COUNT(*) as ct
FROM sc
GROUP BY SId
HAVING ct=2;
-- 3rd, 关联学生表,输出学生姓名
SELECT
a.sid, b.Sname
FROM (
SELECT
sid,
COUNT(*) as ct
FROM sc
GROUP BY SId
HAVING ct=2) a
LEFT JOIN student b
ON a.sid = b.SId;
21. 查询男生、女生人数
-- 21. 查询男生、女生人数
-- “不同性别”, “人数”
-- 1st, 锁定表,学生表
-- 2nd, 按照性别进行分组统计
SELECT
Ssex,
COUNT(*) as ct
FROM student
GROUP BY Ssex;
22. 查询名字中含有‘风’字的学生信息
-- 22. 查询名字中含有‘风’字的学生信息
-- 关键词,“名字中含有‘风’”,“学生信息”
-- 1st, 锁定表,学生表
-- 2nd, 使用like操作符,%为占位符
SELECT
*
FROM student
WHERE Sname LIKE '%风%';
23. 查询同名同性别学生名单,并统计同名同性别人数
-- 23. 查询同名同性别学生名单,并统计同名同性别人数
-- 关键词,“同名同性别”,“人数”
-- 1st, 锁定表,学生表
-- 2nd, 自连接查询,筛选出名字,性别相同
SELECT
a.*
FROM student a
INNER JOIN student b
ON a.Sname = b.Sname AND a.Ssex = b.Ssex AND a.SId != b.SId;
-- 3rd, 统计同名同性别的人数
SELECT
Sname,
Ssex,
COUNT(*) as ct
FROM (SELECT
a.*
FROM student a
INNER JOIN student b
ON a.Sname = b.Sname AND a.Ssex = b.Ssex AND a.SId != b.SId) a
GROUP BY Sname, Ssex;
24. 查询1990年出生的学生名单
-- 24. 查询1990年出生的学生名单
-- 关键词,“出生日期”
-- 1st, 锁定表, 学生表
SELECT * FROM student;
-- 2nd, 使用year(), 筛选出1900年出生的学生
SELECT
*
FROM student
WHERE YEAR(Sage)='1990';
-- left()
SELECT
*
FROM student
WHERE left(Sage, 4)='1990';
25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
-- 25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
-- 关键词,“平均成绩”,“排序”
-- 1st, 锁定表,成绩表
-- 2nd, 计算每门课程的平均成绩
SELECT
CId,
AVG(score) as avg_score
FROM sc
GROUP BY CId;
-- 3rd, 排序(按照平均成绩降序,课程编号升序)
SELECT
CId,
AVG(score) as avg_score
FROM sc
GROUP BY CId
ORDER BY avg_score DESC, cid ASC;
26. 查询平均成绩大于等于 85 的所有学生的学号,姓名和平均成绩
-- 26. 查询平均成绩大于等于 85 的所有学生的学号,姓名和平均成绩
-- 关键词,“平均成绩”,“学号”,“姓名”
-- 1st, 锁定表,成绩表,学生表
-- 2nd, 分组聚合求出每个学生平均分数,并筛选出平均分大于等于85分的学生
SELECT
sid,
AVG(score) AS avg_score
FROM sc
GROUP BY SId
HAVING avg_score >= 85;
-- 3rd, 关联学生表,获取学生姓名
SELECT
a.sid, b.Sname, avg_score
FROM (
SELECT
sid,
AVG(score) AS avg_score
FROM sc
GROUP BY SId
HAVING avg_score >= 85) a
LEFT JOIN student b
ON a.sid = b.SId;
27. 查询课程名称为“数学”,且分数低于60的学生姓名和分数
-- 27. 查询课程名称为“数学”,且分数低于60的学生姓名和分数
-- 关键词,“课程名称”,“分数”, “学生姓名”
-- 1st, 课程表,成绩表,学生表
-- 2nd, 求出课程名称为数学的课程编号
SELECT cid FROM course WHERE Cname='数学';
-- 3rd, 成绩表关联学生表,查询数学分数低于60分的学生信息
SELECT
b.SId,
b.Sname,
a.CId,
a.score
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
WHERE CId=(SELECT cid FROM course WHERE Cname='数学') AND score<60;
28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
-- 28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
-- 关键词,“所有学生”,“课程”,“分数”
-- 1st, 锁定表,学生表,成绩表
-- 2nd, 学生表左连接成绩表
SELECT
*
FROM student a
LEFT JOIN sc b
ON a.SId = b.SId;
29.查询任何一门课程成绩在70分以上的姓名,课程名称和分数
-- 29.查询任何一门课程成绩在70分以上的姓名,课程名称和分数
-- 关键词,“学生姓名”,“课程名称”,“分数”
-- 1st, 锁定表, 学生表,课程表,成绩表
-- 2nd, 关联成绩表和课程表,并筛选出成绩在70分以上的记录
SELECT
*
FROM sc a
LEFT JOIN course b
ON a.CId = b.CId
WHERE a.score>70;
-- 3rd, 关联学生表,获取学生姓名
SELECT
Sname,Cname,score
FROM sc a
LEFT JOIN course b
ON a.CId = b.CId
LEFT JOIN student c
ON a.SId = c.SId
WHERE a.score>70;
30. 查询存在不及格的课程
-- 30. 查询存在不及格的课程
-- 关键词,"不及格", "课程"
-- 1st, 锁定表,成绩表,课程表
-- 2nd, 筛选出低于60分的课程的cid
SELECT
DISTINCT CId
FROM sc
WHERE score<60;
-- 3rd, 使用子查询,获取课程信息
SELECT
*
FROM course
WHERE CId IN (SELECT
DISTINCT CId
FROM sc
WHERE score<60);
31. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
-- 31. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
-- 关键词,“课程编号”,“成绩”, “学生学号”,“姓名”
-- 1st, 锁定表,成绩表,学生表
-- 2nd, 关联查询
SELECT
a.*,
b.Sname
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
WHERE a.CId = '01' AND a.score>=80;
32. 求每门课程的学生人数
-- 32. 求每门课程的学生人数
-- 关键词,“每门课程”, “人数”
-- 1st, 锁定表,成绩表
-- 2nd, 分组聚合
SELECT
cid,
COUNT(*) AS ct
FROM sc
GROUP BY cId;
33. 假设成绩不重复,查询选修“张三” 老师所授课程的学生中,成绩最高的学生信息及其成绩
-- 33. 假设成绩不重复,查询选修“张三” 老师所授课程的学生中,成绩最高的学生信息及其成绩
-- 关键词,“张三老师”,“成绩不重复”,“成绩最高”,“学生信息”,“成绩”
-- 锁定表, 4张表
-- 1st, 关联4张表
SELECT
*
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId;
-- 2nd, 增加筛选条件,‘张三’老师
SELECT
*
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId
WHERE Tname = '张三';
-- 3rd, 按照分数排序,只显示第一条记录(limit)
SELECT
b.*, score, Tname
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId
WHERE Tname = '张三'
ORDER BY score DESC
LIMIT 1;
34. 假设成绩有重复的情况下,查询选修‘张三’老师所授的学生中,成绩最高的学生信息及其成绩
-- 34. 假设成绩有重复的情况下,查询选修‘张三’老师所授的学生中,成绩最高的学生信息及其成绩
-- 关键词,“张三老师”, “成绩重复”,“成绩最高”,“学生信息”,“成绩”
-- 1st,锁定表,教师表,课程表,成绩表,学生表
-- 2nd, 关联4张表,并筛选出选修‘张三’老师所授课程的记录
SELECT
*
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId
WHERE Tname = '张三';
-- 3rd, 使用dense_rank()进行排序
SELECT
b.*, a.score, d.Tname,
DENSE_RANK() over (ORDER BY score DESC) AS score_rank
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId
WHERE Tname = '张三';
-- 4th, 筛选出第1名
SELECT
*
FROM (
SELECT
b.*, a.score, d.Tname,
DENSE_RANK() over (ORDER BY score DESC) AS score_rank
FROM sc a
LEFT JOIN student b
ON a.SId = b.SId
LEFT JOIN course c
ON a.CId = c.CId
LEFT JOIN teacher d
ON c.Tid = d.TId
WHERE Tname = '张三') a
WHERE score_rank = 1;
35. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
-- 35. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
-- 关键词,“不同课程”、“成绩相同”
-- 1st, 锁定表,成绩表
-- 2nd, 自连接成绩表,连接条件是学生编号相同、课程编号不同、成绩相同
SELECT
*
FROM sc a
INNER JOIN sc b
ON a.SId = b.SId AND a.CId != b.CId AND a.score = b.score;
-- 3rd, 去重
SELECT
DISTINCT a.*
FROM sc a
INNER JOIN sc b
ON a.SId = b.SId AND a.CId != b.CId AND a.score = b.score;
36. 查询每门科目成绩最好的前两名
-- 36. 查询每门科目成绩最好的前两名
-- 关键词,“每门科目”, “成绩最好前两名”
-- 1st, 锁定表,成绩表
-- 2nd, 使用dense_rank()排名
SELECT
*,
DENSE_RANK() over (PARTITION by CId ORDER BY score DESC) AS score_rank
FROM sc;
-- 3rd, 筛选出前两名
SELECT
*
FROM (SELECT
*,
DENSE_RANK() over (PARTITION by CId ORDER BY score DESC) AS score_rank
FROM sc) a
WHERE score_rank<=2;
37. 统计每门课程的学生选修人数(超过5人的课程才统计)
-- 37. 统计每门课程的学生选修人数(超过5人的课程才统计)
-- 关键词,“每门课程”,“选修人数”、“超过5人才统计”
-- 1st, 锁定表,成绩表
-- 2nd, 分组聚合,求每门课程的选修人数
SELECT
cid,
COUNT(*) AS ct
FROM sc
GROUP BY CId;
-- 3rd, 筛选出选修人数大于5的记录
SELECT
cid,
COUNT(*) AS ct
FROM sc
GROUP BY CId
HAVING ct>5;
38. 检索至少选修两门课程的学生学号
-- 38. 检索至少选修两门课程的学生学号
-- 关键词,“选修课程”, “学生学号”
-- 1st, 锁定表, 成绩表
-- 2nd, 分组聚合,求出每名学生的选修课程数
SELECT
SId,
COUNT(*) as ct
FROM sc
GROUP BY SId;
-- 3rd, 筛选出选修课程数大于等于2的学生
SELECT
SId,
COUNT(*) as ct
FROM sc
GROUP BY SId
HAVING ct>=2;
39. 查询选修了全部课程的学生信息
-- 39. 查询选修了全部课程的学生信息
-- 关键词,“选修全部课程”,“学生信息”
-- 1st, 锁定表,学生表,成绩表,课程表
-- 2nd, 求出课程表的总课程数
SELECT COUNT(*) FROM course;
-- 3rd, 求出每名学生的选修课程数
SELECT
SId,
COUNT(*)
FROM sc
GROUP BY SId;
-- 4th, 筛选出学习全部课程的学生sid
SELECT
SId,
COUNT(*)
FROM sc
GROUP BY SId
HAVING count(*) = (SELECT COUNT(*) FROM course);
-- 5th, 使用子查询,获取学生信息
SELECT
*
FROM student
WHERE SId in (
SELECT
SId
FROM sc
GROUP BY SId
HAVING count(*) = (SELECT COUNT(*) FROM course));
40. 查询各学生的年龄,只按年份计算
-- 40. 查询各学生的年龄,只按年份计算
-- 关键词,“年龄”, “按年份计算”
-- 1st, 锁定表,学生表
-- 2nd, 使用now(),year()函数计算年龄
SELECT YEAR('1990-01-01 00:00:00');
SELECT NOW();
SELECT
*,
(YEAR(NOW()) - YEAR(Sage)) AS age
FROM student;
41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
-- 41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
-- 关键词,“年龄”,“当前月日<出生年月的月日则,年龄减一”
-- 1st, 锁定表,学生表
-- 2nd, 使用now(),timestamdiff()函数计算年龄
-- timestamdiff()日期相减函数的用法
SELECT TIMESTAMPDIFF(YEAR, '1990-02-01 00:00:00', '2020-01-01 00:00:00');
SELECT TIMESTAMPDIFF(YEAR, '1990-02-01 00:00:00', '2020-04-01 00:00:00');
SELECT TIMESTAMPDIFF(DAY, '1990-02-01 00:00:00', '2020-03-01 00:00:00');
SELECT TIMESTAMPDIFF(HOUR, '1990-02-01 00:00:00', '2020-01-02 00:00:00');
SELECT
*,
TIMESTAMPDIFF(YEAR, Sage, NOW())
FROM student;
42. 查询本周过生日的学生
-- 42. 查询本周过生日的学生
-- 关键词, "周数"
-- 1st, 锁定表,学生表
-- 2nd, 使用week()函数查询
SELECT WEEK('1990-8-14 00:00:00');
SELECT * FROM student;
SELECT
*,
WEEK(Sage),
WEEK(NOW())
FROM student
WHERE WEEK(Sage)=week(NOW());
43. 查询下周过生日的学生
-- 43. 查询下周过生日的学生
-- 关键词,“周数”
-- 1st, 锁定表,学生表
-- 2nd, 使用week()函数查询
SELECT
*,
WEEK(Sage),
WEEK(NOW())+1
FROM student
WHERE WEEK(Sage)=week(now())+1;
44. 查询本周过生日的学生
-- 44. 查询本周过生日的学生
-- 关键词,“月份”
-- 1st, 锁定表,学生表
-- 2nd, 使用month()函数查询
SELECT
*,
MONTH(Sage),
MONTH(NOW())
FROM student
WHERE MONTH(Sage)=MONTH(NOW());
45. 查询下月过生日的学生
-- 45. 查询下月过生日的学生
-- 关键词,“月份”
-- 1st, 锁定表,学生表
-- 2nd, 使用month()函数查询
SELECT
*,
MONTH(Sage),
MONTH(NOW())+1
FROM student
WHERE MONTH(Sage)=MONTH(NOW())+1;
参考链接- bilibili-数据蛙-数据分析面试必备,45道SQL题目
参考链接- Mysql_45道练习题