数据库学习5:数据库学习入门41-50题(基于MySQL)

SQL面试必会50题123

41. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 (重点)

先根据学号和成绩分类:

SELECT s_id,s_score
FROM Score
GROUP BY s_id,s_score

得到结果如下,该表展示了每个学号不同课程的分数共有几种,比方说语文数学英语都为80分,那么该学号下只会显示一个80分;若语文数学为60分,英语为70分,那么该学号下会显示一个60分,一个70分。
在这里插入图片描述
接下来我们就要选出,选课超过1门且不同课程分数相同的学生学号和姓名。

SELECT s_id FROM 
(
SELECT a.s_id,a.s_score
FROM Score AS a
INNER JOIN
(
SELECT s_id FROM Score
GROUP BY s_id HAVING COUNT(DISTINCT c_id) > 1 # 选课超过1门的学生学号
) AS b ON a.s_id = b.s_id
GROUP BY a.s_id,a.s_score
) AS c
GROUP BY s_id HAVING COUNT(s_id) > 1

在这里插入图片描述

42题有重复

43. 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列(不重要)

SELECT a.c_id,COUNT(DISTINCT a.s_id)'选课人数' ,b.c_name'课程名称'
FROM Score AS a
INNER JOIN Course AS b ON a.c_id = b.c_id
GROUP BY c_id HAVING COUNT(DISTINCT a.s_id) > 5
ORDER BY 选课人数 DESC,c_id ASC

在这里插入图片描述

44. 检索至少选修两门课程的学生学号(不重要)

SELECT s_id,COUNT(DISTINCT c_id)'选课人数'
FROM Score 
GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2

在这里插入图片描述

45. 查询选修了全部课程的学生信息(重点划红线地方)

SELECT s_id,COUNT(DISTINCT c_id)'选课门数' FROM Score
GROUP BY s_id HAVING COUNT(DISTINCT c_id) = (SELECT COUNT(DISTINCT c_id) FROM Course)

在这里插入图片描述

46. 查询各学生的年龄(精确到月份)

SELECT s_id,s_birth,FLOOR(DATEDIFF(CURDATE(),s_birth)/365)'年龄' FROM Student

在这里插入图片描述

FLOOR函数:向下取整
ROUND函数:四舍五入

47. 查询没学过“张三”老师讲授的任一门课程的学生姓名(还可以,自己写的,答案中没有)

SELECT s_id'学号',s_name FROM Student
WHERE s_id NOT IN
(
	SELECT a.s_id
	FROM Student AS a
	INNER JOIN Score AS b ON a.s_id = b.s_id
	INNER JOIN Course AS c ON b.c_id = c.c_id
	INNER JOIN Teacher AS d ON c.t_id = d.t_id
	WHERE d.t_name = '张三'
)

在这里插入图片描述

易错点:选择t_name != '张三’的学号,错误之处在于,比如说1号学生选了张三和李四的课,在表上会放置在两条信息,一条是1号学生选张三课的成绩,一条是1号学生选李四课的成绩,当用t_name != '张三’时,1号学生选李四课的成绩的那条信息也会被选出来,你再选择学号,1号也会被当成没有选过张三课的学生。

48. 查询下周过生日的同学

错误做法

SELECT WEEK('20200101',0) -- 0
SELECT WEEK('20200101',1) -- 1

查询满足条件“week(出生日期,1)=week(现在日期,1)+1”的同学

SELECT s_id,s_name,s_birth FROM Student 
WHERE WEEK(s_birth,1) = WEEK(CURDATE(),1) + 1

但这会带来一个问题,出生那年生日是第几周可能和今年生日是第几周有一周的差距,这会导致条件“week(出生日期,1)=week(现在日期,1)+1”不可用。

正确做法
我们可以把每个人的生日放到当年来,再做比较,比方说’1990-07-01’先置换成’2020-07-01’,再来比较week('2020-07-01',1)week('当前日期',1)的周数是否一样。由于没有当下日期下周过生日的人,不妨考虑’2020-06-27’下周过生日的情况。
置换年份通过substringconcat两个函数来完成。

SUBSTRING(字符串,a,b):从字符串的第a位开始取b个字符
CONCAT(字符串1,字符串2,…):将多个字符串连在一起

SELECT * FROM Student
WHERE WEEK(CONCAT('2020-',SUBSTRING(s_birth,6,5)),1) = WEEK('2020-06-27',1) + 1

在这里插入图片描述

49. 查询本月过生日的学生(无法使用week、date(now())

SELECT * FROM Student
WHERE MONTH(s_birth) = MONTH(CURDATE())

在这里插入图片描述

50. 查询下月过生日的学生(无法使用week、date(now())

SELECT * FROM Student
WHERE MONTH(s_birth) = MONTH(CURDATE()) + 1

上面这个做法,欠缺了当前月若是12月的情况,以下是修正:

SELECT * FROM Student WHERE
CASE WHEN MONTH(CURDATE()) = 12 
	 THEN 
	   	 MONTH(s_birth) = 1 
	 ELSE 
		 MONTH(s_birth) = MONTH(CURDATE()) + 1 
	 END

  1. B站视频专栏-up主:陆小亮-【数据分析】- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家 ↩︎

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

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

发布了14 篇原创文章 · 获赞 7 · 访问量 3253

猜你喜欢

转载自blog.csdn.net/sunsimiaofromsh/article/details/104741074