ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

SQL 45道例题

2021-06-02 22:00:40  阅读:214  来源: 互联网

标签:课程 SQL -- 45 score SId sc 例题 SELECT


文章目录

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() 区别

  1. ROW_NUMBER(): 依次排序,不会出现相同排名
  2. RANK(): 出现相同排名时,跳跃排名
  3. 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道练习题

标签:课程,SQL,--,45,score,SId,sc,例题,SELECT
来源: https://blog.csdn.net/weixin_31948131/article/details/116432533

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有