SQL面试必会50题123
21.查询不同老师所教不同课程平均分从高到低显示(不重点)
想法一:以课程为主体,求平均分
SELECT a.c_id,b.c_name'课程名',AVG(a.s_score)'平均分'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id
ORDER BY 平均分 DESC
想法二:以老师为主体,求平均分
SELECT c.t_id,c.t_name,AVG(a.s_score)'平均分'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
INNER JOIN Teacher AS c ON b.t_id = c.t_id
GROUP BY t_id,t_name
ORDER BY 平均分 DESC
22.查询所有课程的成绩第2名到第3名的学生信息及该课程成绩(重要,与25题类似)
利用窗口函数row_number(),构造一张临时表。
CREATE TEMPORARY TABLE temp AS
(
SELECT a.s_id'学号',a.c_id'课程',a.s_score'成绩',b.s_name'姓名',b.s_sex'性别',b.s_birth'生日',
row_number() over(PARTITION BY a.c_id ORDER BY a.s_score DESC)'rank'
FROM Score AS a
INNER JOIN Student AS b ON a.s_id = b.s_id
) -- 临时表
构造临时表语法:CREATE TEMPORARY TABLE 临时表名 AS (SELECT * FROM *)
删除临时表语法: DROP TEMPORARY TABLE 临时表名;
SELECT temp.学号,temp.姓名,
temp.性别,temp.生日,
temp.课程,temp.成绩,
temp.rank'排名'
FROM temp
WHERE temp.rank IN (2,3)
提取临时表中列时,每一列前面都要带上“临时表名.”
23.使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计各分数段人数:课程ID和课程名称(重点,与18题类似,CASE WHEN)
SUM做计数器:
SELECT b.c_id,b.c_name'姓名',
SUM(CASE WHEN a.s_score >= 85 AND a.s_score <= 100 THEN 1 ELSE 0 END)'[100-85]',
SUM(CASE WHEN a.s_score >= 70 AND a.s_score < 85 THEN 1 ELSE 0 END)'[85-70]',
SUM(CASE WHEN a.s_score >= 60 AND a.s_score < 70 THEN 1 ELSE 0 END)'[70-60]',
SUM(CASE WHEN a.s_score < 60 THEN 1 ELSE 0 END)'[<60]'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id,c_name
COUNT做计数器:
SELECT b.c_id,b.c_name'姓名',
COUNT(CASE WHEN a.s_score >= 85 AND a.s_score <= 100 THEN 1 ELSE NULL END)'[100-85]',
COUNT(CASE WHEN a.s_score >= 70 AND a.s_score < 85 THEN 1 ELSE NULL END)'[85-70]',
COUNT(CASE WHEN a.s_score >= 60 AND a.s_score < 70 THEN 1 ELSE NULL END)'[70-60]',
COUNT(CASE WHEN a.s_score < 60 THEN 1 ELSE NULL END)'[<60]'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id,c_name
COUNT做计数器要注意,CASE WHEN语句中ELSE后面是NULL,如果是0的话,COUNT(0)= 1,而NULL是不计入数的。
24.查询学生平均成绩及其名次(重点,与19题类似)
SELECT s_id'学号',AVG(s_score)'平均分',
rank() over(ORDER BY AVG(s_score) DESC)'平均分排名'
FROM Score
GROUP BY s_id
若窗口函数over后的括号里没有PARTITION BY,就说明将整张表作为一类来排序。
25.查询各科成绩前三名的记录(不考虑成绩并列情况)(重点,与22题类似)
CREATE TEMPORARY TABLE temp AS
(
SELECT s_id'学号',c_id'课程',s_score'成绩',
row_number() over(PARTITION BY c_id ORDER BY s_score DESC)'rank'
FROM Score
) -- 临时表
SELECT temp.`课程`,temp.`学号`,temp.`成绩`,temp.rank'排名前三'
FROM temp
WHERE temp.rank IN (1,2,3)
26.查询每门课程被选修的学生数(不重点)
SELECT a.c_id,b.c_name'课程名称',COUNT(DISTINCT a.s_id)'选课人数'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id,c_name
27.查询出只有两门课程的全部学生的学号和姓名(不重点)
法一
SELECT a.s_id,b.s_name'姓名'
FROM Score AS a
INNER JOIN Student AS b ON a.s_id = b.s_id
GROUP BY s_id,s_name HAVING COUNT(DISTINCT a.c_id) = 2
法二 推荐,性能好
SELECT s_id'学号',s_name'姓名' FROM Student
WHERE s_id IN
(
SELECT s_id FROM Score
GROUP BY s_id HAVING COUNT(DISTINCT c_id) = 2
)
28.查询男生、女生人数(不重点)
SELECT s_sex'性别',COUNT(DISTINCT s_id) '数目'
FROM Student
GROUP BY s_sex
SELECT s_sex'性别',COUNT(s_sex) '数目' -- 不能加DISTINCT
FROM Student
GROUP BY s_sex
SELECT
SUM(CASE WHEN s_sex = '男' THEN 1 ELSE 0 END)'男生人数',
SUM(CASE WHEN s_sex = '女' THEN 1 ELSE 0 END)'女生人数'
FROM Student
SELECT
COUNT(CASE WHEN s_sex = '男' THEN 1 ELSE NULL END)'男生人数',
COUNT(CASE WHEN s_sex = '女' THEN 1 ELSE NULL END)'女生人数'
FROM Student
29.查询名字中含有"风"字的学生信息(不重点)
SELECT s_id'学号',s_name'姓名',s_sex'性别',s_birth'生日'
FROM Student
WHERE s_name LIKE '%风%'
30题忽略掉
B站视频专栏-up主:陆小亮-【数据分析】- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家 ↩︎
知乎-猴子-常见的SQL面试题:经典50题https://zhuanlan.zhihu.com/p/38354000 ↩︎
知乎-小番茄-SQL面试必会50题https://zhuanlan.zhihu.com/p/43289968 ↩︎