数据库学习2:数据库学习入门11-20题(基于MySQL)

SQL面试必会50题12

11. 查询至少有一门课与学号为“01”的学生所学课程相同的学生的学号和姓名(重点)

法一

先查询学号为“01”的学生所学课程:

SELECT c_id FROM Score
WHERE s_id = '01'

数据库学习2:数据库学习入门11-20题(基于MySQL)_第1张图片

选出学号不为“01”且选的课程为“01”“02”“03”的同学学号:

SELECT s_id'学号',s_name'姓名' FROM Student 
WHERE s_id IN
(
SELECT DISTINCT s_id FROM Score
WHERE c_id IN
	(
	SELECT c_id FROM Score
	WHERE s_id = '01'
	) AND s_id != '01'
)

数据库学习2:数据库学习入门11-20题(基于MySQL)_第2张图片
法二

先构造一个内联表:

SELECT *
FROM Student AS a
INNER JOIN
(
SELECT DISTINCT s_id FROM Score
WHERE c_id IN
	(
	SELECT c_id FROM Score
	WHERE s_id = '01'
	) AND s_id != '01'
) AS b ON a.s_id = b.s_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第3张图片

再从中选出学号,姓名的信息:

SELECT a.s_id'学号',a.s_name'姓名'
FROM Student AS a
INNER JOIN
(
SELECT DISTINCT s_id FROM Score
WHERE c_id IN
	(
	SELECT c_id FROM Score
	WHERE s_id = '01'
	) AND s_id != '01'
) AS b ON a.s_id = b.s_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第4张图片

12. 查询和“01”号同学所学课程完全相同的其他同学的学号(重点,易错)

本题小亮老师在视频讲解中第一遍也讲错了,博主认为这个错点确实很难注意到,故在此处强调一下⚠️

易错点1:没有考虑到学号02的情况。
数据库学习2:数据库学习入门11-20题(基于MySQL)_第5张图片
先选取了选了课程01,02,03中某一门的学生学号,再从中选出选了和01学生课程数一样的学生学号,这个做法没有考虑到可能存在课程04,学生选了课程01,02,04。实质上,这个错误是由IN函数是从(01,02,03)中选一个满足就可以而造成的。
数据库学习2:数据库学习入门11-20题(基于MySQL)_第6张图片

易错点2:没有考虑到学号03的情况。
数据库学习2:数据库学习入门11-20题(基于MySQL)_第7张图片代码从Score表中选出课程为01,02,03的学生学号,相当于只选了下表前三条的学号,也就是选出了3个学号03,因此03号学生也能通过选课数为3的条件,被最终选出来。这个错误实质上没有考虑到可能学生01选的不是全部课程的情况,并且对Score表的排列没有了解——该表把每个学号对应课程成绩拆做一条,因此在选择时,超出01,02,03的会被删除。
数据库学习2:数据库学习入门11-20题(基于MySQL)_第8张图片
数据库学习2:数据库学习入门11-20题(基于MySQL)_第9张图片

正确解题思路:1.查询01号学生选了课程01,02,03;
2.选出所学课不在(01,02,03)中的同学 → 删 除 \rightarrow 删除
3.剩下的同学肯定选了(01,02,03)中的某几门课,判断所学的课程数是否等于3,等于3的同学一定是选了课程01,02,03。

选出所学课不在(01,02,03)中的同学:

SELECT s_id FROM Score
WHERE c_id NOT IN
(
SELECT c_id FROM Score
WHERE s_id = '01'
)

剩下的同学肯定选了(01,02,03)中的某几门课,判断所学的课程数是否等于3:

SELECT s_id'学号' FROM Score
WHERE s_id != '01'
GROUP BY s_id 
HAVING COUNT(DISTINCT c_id) =
(SELECT COUNT(DISTINCT c_id) FROM Score WHERE s_id = '01') 
-- 最后一行语句计算的是学号01的学生共修了几门课

反选2.的情况并和3.的情况做并集:

SELECT s_id'学号' FROM Score
WHERE s_id != '01'
GROUP BY s_id 
HAVING COUNT(DISTINCT c_id) =
(SELECT COUNT(DISTINCT c_id) FROM Score WHERE s_id = '01')
AND s_id NOT IN -- 反选
(
SELECT s_id FROM Score
WHERE c_id NOT IN
	(
	SELECT c_id FROM Score
	WHERE s_id = '01'
	)
)

数据库学习2:数据库学习入门11-20题(基于MySQL)_第10张图片

13题与5题重复,14题缺失

15. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩(重点)

法一

解题思路:

  1. 选出至少两门课分数小于60分的学生学号;
  2. 以学号为标准内联结Student表和Score表;
  3. 将内联表以学号/姓名作为分类,从中查询满足1.的学号,姓名,并计算平均分。

选出至少两门课分数小于60分的学生学号:

SELECT s_id FROM Score
WHERE s_score < 60
GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2

以学号为标准内联结Student表和Score表,将内联表以学号/姓名作为分类,从中查询满足1.的学号,姓名,并计算平均分。

SELECT a.s_id,a.s_name,AVG(b.s_score) 
FROM Student AS a
INNER JOIN
Score AS b ON a.s_id = b.s_id
WHERE a.s_id IN
(
	SELECT s_id FROM Score
	WHERE s_score < 60
	GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2
)
GROUP BY s_id,s_name

法二 这是博主自己想的做法,如有错误欢迎提出

解题思路:

  1. 选出分数小于60分的学生的学号和课程,查询至少两门课不及格的学生学号、这些学生的平均分;
  2. 以学号为标准内联结Student表和1.中表;
  3. 选出平均分不为NULL的学号。

选出分数小于60分的学生的学号和课程,查询至少两门课不及格的学生学号、这些学生的平均分:

SELECT s_id,AVG(s_score)'average' FROM Score
WHERE s_score < 60
GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2

以学号为标准内联结Student表和1.中表

SELECT a.s_id,a.s_name,b.average
FROM Student AS a
LEFT JOIN
(
	SELECT s_id,AVG(s_score)'average' FROM Score
	WHERE s_score < 60
	GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2
) AS b ON a.s_id = b.s_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第11张图片

选出平均分不为NULL的学号:

SELECT a.s_id,a.s_name,b.average
FROM Student AS a
LEFT JOIN
(
	SELECT s_id,AVG(s_score)'average' FROM Score
	WHERE s_score < 60
	GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2
) AS b ON a.s_id = b.s_id
WHERE average IS NOT NULL

易错点:平均分不为NULL不是“average != NULL”,而是“average IS NOT NULL”

数据库学习2:数据库学习入门11-20题(基于MySQL)_第12张图片

16. 检索"01"课程分数小于60,按分数降序排列的学生信息(和34题重复,不重点)

SELECT a.s_id'学号',a.s_name'姓名',b.s_score'分数' FROM Student AS a
INNER JOIN Score AS b ON a.s_id = b.s_id
WHERE b.c_id = '01' AND b.s_score < 60
ORDER BY s_score DESC

数据库学习2:数据库学习入门11-20题(基于MySQL)_第13张图片

17. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(重点,CASE WHEN

本题目标是构造如下表格:
在这里插入图片描述
难点:如何把每门课的成绩提取出来?
利用CASE WHEN来提取!

SELECT s_id'学号', 
MAX(CASE WHEN c_id = '01' THEN s_score ELSE NULL END)'语文',
MAX(CASE WHEN c_id = '02' THEN s_score ELSE NULL END)'数学',
MAX(CASE WHEN c_id = '03' THEN s_score ELSE NULL END)'英文',
AVG(s_score)'平均分'
FROM Score
GROUP BY s_id 
ORDER BY AVG(s_score) DESC

MAX函数的调用是因为GROUP BY函数使用后,只能查询GROUP BY函数后的条件以及统计项,此处CASE WHEN后c_id=‘01’只能取出一个分数,所以即使加上MAX依然是该分数。

数据库学习2:数据库学习入门11-20题(基于MySQL)_第14张图片

18. 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率。及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 (超级重点CASE WHEN

SELECT 
a.c_id,
b.c_name'课程名',
MAX(a.s_score)'最高分',
MIN(a.s_score)'最低分',
AVG(a.s_score)'平均分',
SUM(CASE WHEN a.s_score >= 60 THEN 1 ELSE 0 END)/COUNT(a.s_id)'及格率', -- 由于GROUP BY c_id过,故这里会对每一个c_id做前面这个语句
SUM(CASE WHEN a.s_score >= 70 AND a.s_score <80 THEN 1 ELSE 0 END)/COUNT(a.s_id)'中等率',
SUM(CASE WHEN a.s_score >= 80 AND a.s_score <90 THEN 1 ELSE 0 END)/COUNT(a.s_id)'优良率',
SUM(CASE WHEN a.s_score >= 90 THEN 1 ELSE 0 END)/COUNT(a.s_id)'优秀率'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id

CASE WHEN宝典
计算及格率思路:及格率 = count(>=60的学生数)/ count(总人数)
用计数器思路来合计课程及格的人数,当字段满足条件时,将该字段记为‘1’,否则记为‘0’,再将变换后的分数求和,即是满足条件的人数。再除以选课学生人数,完毕。

数据库学习2:数据库学习入门11-20题(基于MySQL)_第15张图片

19. 按各科成绩进行排序,并显示排名(重点,窗口函数row_number,rank,dense_rank3

窗口函数row_number,rank,dense_rank作用区别:
同样同分的情况用三个函数排名得到的结果不同。数据库学习2:数据库学习入门11-20题(基于MySQL)_第16张图片

row_number()

SELECT a.s_id'学号',b.c_name'课程',a.s_score'成绩',
row_number() over(PARTITION BY a.c_id ORDER BY a.s_score DESC)'排名'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第17张图片
rank()

SELECT a.s_id'学号',b.c_name'课程',a.s_score'成绩',
rank() over(PARTITION BY a.c_id ORDER BY a.s_score DESC)'排名'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第18张图片
dense_rank()

SELECT a.s_id'学号',b.c_name'课程',a.s_score'成绩',
dense_rank() over(PARTITION BY a.c_id ORDER BY a.s_score DESC)'排名'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id

数据库学习2:数据库学习入门11-20题(基于MySQL)_第19张图片

三种窗口函数的用法都为:窗口函数 + over(PARTITION BY 分类依据(例如,此处分为每门课程来排序) ORDER BY 排序标准(例如,此处根据分数高低来排序) DESC)

20. 查询学生的总成绩并进行排名(不重点)

SELECT s_id'学号',SUM(s_score)'总成绩' FROM Score
GROUP BY s_id
ORDER BY 总成绩 DESC

数据库学习2:数据库学习入门11-20题(基于MySQL)_第20张图片


  1. 知乎-小番茄-SQL面试必会50题https://zhuanlan.zhihu.com/p/43289968 ↩︎

  2. 知乎-猴子-常见的SQL面试题:经典50题https://zhuanlan.zhihu.com/p/38354000 ↩︎

  3. mysql8.0窗口函数:rank,dense_rank,row_number 使用上的区别https://yq.aliyun.com/articles/593698 ↩︎

你可能感兴趣的:(数据库SQL·所践所习,mysql,数据库)