先根据学号和成绩分类:
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
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
SELECT s_id,COUNT(DISTINCT c_id)'选课人数'
FROM Score
GROUP BY s_id HAVING COUNT(DISTINCT c_id) >= 2
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)
SELECT s_id,s_birth,FLOOR(DATEDIFF(CURDATE(),s_birth)/365)'年龄' FROM Student
FLOOR函数:向下取整
ROUND函数:四舍五入
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号也会被当成没有选过张三课的学生。
错误做法
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’下周过生日的情况。
置换年份通过substring
和concat
两个函数来完成。
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
SELECT * FROM Student
WHERE MONTH(s_birth) = MONTH(CURDATE())
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
B站视频专栏-up主:陆小亮-【数据分析】- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家 ↩︎
知乎-猴子-常见的SQL面试题:经典50题https://zhuanlan.zhihu.com/p/38354000 ↩︎
知乎-小番茄-SQL面试必会50题https://zhuanlan.zhihu.com/p/43289968 ↩︎