MySQL面试实战:15道高频查询场景与核心函数解析
1. 学生成绩对比查询实战在面试中最常被问到的就是多课程成绩对比查询这类题目能考察你对JOIN操作和子查询的掌握程度。我当年第一次面试就被问到了类似问题结果因为紧张写了个错误答案现在想起来都觉得尴尬。先来看第一个经典场景查询01课程比02课程成绩高的学生信息。这个需求在实际业务中很常见比如对比用户两个时间段的消费金额。核心思路是把同一学生在不同课程的成绩记录关联起来SELECT s.*, t1.score AS 01课程分数, t2.score AS 02课程分数 FROM (SELECT * FROM t_mysql_score WHERE cid01) t1, (SELECT * FROM t_mysql_score WHERE cid02) t2, t_mysql_student s WHERE s.sid t1.sid AND s.sid t2.sid AND t1.score t2.score这里使用了派生表的方式先筛选出01和02课程的成绩记录再通过学生ID关联。有个坑要注意如果学生只选修了其中一门课这种内连接会直接过滤掉该学生。我有次线上排查数据异常就栽在这个问题上。更复杂的场景是查询存在01课程但可能不存在02课程的情况不存在时显示null。这种需求在用户行为分析中很常见比如统计看过商品详情但未下单的用户SELECT t1.*, t2.score AS 02课程 FROM (SELECT * FROM t_mysql_score WHERE cid01) t1 LEFT JOIN (SELECT * FROM t_mysql_score WHERE cid02) t2 ON t1.sid t2.sidLEFT JOIN能确保左表记录全部保留右表不匹配时填充NULL。实际项目中我曾用这个方案统计功能使用率比用子查询性能提升了40%。2. 多条件筛选与聚合分析实际业务中最头疼的就是各种带条件的统计需求。比如查询平均成绩≥60分的学生这个在电商场景类似统计客单价达标用户SELECT s.sid, s.sname, ROUND(AVG(sc.score)) AS 平均成绩 FROM t_mysql_student s JOIN t_mysql_score sc ON s.sid sc.sid GROUP BY s.sid, s.sname HAVING 平均成绩 60这里有几个关键点1) GROUP BY要包含所有非聚合字段 2) HAVING过滤聚合结果 3) ROUND四舍五入。我见过有人把过滤条件写在WHERE里导致报错记住WHERE在GROUP之前执行不能过滤聚合结果。更复杂的是查询两门及以上不及格课程的学生SELECT s.sid, s.sname, ROUND(AVG(sc.score)) AS 平均成绩, COUNT(sc.cid) AS 不及格课程数 FROM t_mysql_student s JOIN t_mysql_score sc ON s.sid sc.sid WHERE sc.score 60 GROUP BY s.sid, s.sname HAVING 不及格课程数 2这个查询在教务系统中很实用可以自动识别需要学业预警的学生。注意WHERE和HAVING的区别WHERE先过滤单条记录HAVING后过滤分组结果。3. 多表关联与复杂统计实际业务中最考验SQL功力的就是多表关联的复杂统计。比如查询学过张三老师授课的学生信息SELECT s.* FROM t_mysql_student s JOIN t_mysql_score sc ON s.sid sc.sid JOIN t_mysql_course c ON sc.cid c.cid JOIN t_mysql_teacher t ON c.tid t.tid WHERE t.tname 张三这种四级关联在订单分析中很常见用户-订单-商品-品类。关键是要理清表关系学生通过成绩表关联课程课程通过教师ID关联教师。建议先用ER图理清关系再写SQL我有次漏了中间表直接关联导致结果爆炸。更复杂的是各科成绩统计报表需要计算多种比率SELECT c.cid, c.cname, MAX(sc.score) AS 最高分, MIN(sc.score) AS 最低分, ROUND(AVG(sc.score)) AS 平均分, COUNT(sc.score) AS 选修人数, CONCAT(ROUND(SUM(IF(sc.score60,1,0))/COUNT(sc.score)*100),%) AS 及格率 FROM t_mysql_score sc JOIN t_mysql_course c ON sc.cid c.cid GROUP BY c.cid, c.cname ORDER BY 选修人数 DESC, c.cid这个查询用到了IF条件聚合在经营分析报表中很实用。注意CONCAT和ROUND的配合使用以及最后的排序规则。曾经我漏写了GROUP BY导致结果异常排查了半天才发现。4. 高级函数实战应用CASE WHEN是SQL中最强大的条件表达式在数据转置时特别有用。比如按学生展示各科成绩SELECT s.sid, s.sname, MAX(CASE WHEN sc.cid01 THEN sc.score END) AS 语文, MAX(CASE WHEN sc.cid02 THEN sc.score END) AS 数学 FROM t_mysql_student s LEFT JOIN t_mysql_score sc ON s.sid sc.sid GROUP BY s.sid, s.sname这种行转列操作在报表开发中经常使用。注意要用MAX或MIN等聚合函数因为GROUP BY后每个学生有多条记录。我推荐用LEFT JOIN确保没有成绩的学生也能显示。IF函数虽然简单但很实用比如标记优秀学生SELECT s.sid, s.sname, IF(AVG(sc.score)90,优秀,普通) AS 等级 FROM t_mysql_student s LEFT JOIN t_mysql_score sc ON s.sid sc.sid GROUP BY s.sid, s.sname在用户分群、商品打标等场景都会用到这种条件标记。IF函数比CASE WHEN更简洁但只能处理二选一的情况。