最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何用SQL嵌套查询过滤出那些平均分及格的班级?
时间:2026-06-18 08:52:52 编辑:袖梨 来源:一聚教程网
子查询先算各班平均分再筛选,因WHERE不支持聚合函数;HAVING可直接在GROUP BY后过滤,但无法处理空班级或需扩展字段的场景。
用子查询先算出每个班的平均分
核心思路是把“班级平均分”当做一个中间结果,再对这个结果做筛选。不能直接在 WHERE 里写 AVG(score),因为聚合函数不能出现在普通 WHERE 子句中——会报错 ERROR 1111 (HY000): Invalid use of group function。
所以得用子查询先把每个班的平均分算出来,比如:
SELECT class_id, AVG(score) AS avg_scoreFROM studentsGROUP BY class_id
这个结果就是一张临时表,下一步再从中挑出 avg_score >= 60 的记录。
外层查询加条件筛选及格班级
把上面的子查询作为 FROM 子句里的数据源,就能在外层安全地加 WHERE 条件了:
SELECT class_idFROM ( SELECT class_id, AVG(score) AS avg_score FROM students GROUP BY class_id) AS class_avgWHERE avg_score >= 60;
注意几点:
- 子查询必须起别名(如
AS class_avg),否则 MySQL 会报错Every derived table must have its own alias -
AVG()默认忽略NULL值,如果某班有大量缺考(score IS NULL),平均分可能偏高,实际可能不具代表性 - 如果还要查班级名称,得提前关联
classes表,不能只靠class_id—— 子查询里没带class_name
用 HAVING 替代嵌套?小心逻辑陷阱
有人会想:既然要按班级分组再筛平均分,直接用 HAVING 不更简单?确实可以:
SELECT class_idFROM studentsGROUP BY class_idHAVING AVG(score) >= 60;
但要注意,这和嵌套查询不是完全等价的:
-
HAVING是对分组后的结果过滤,前提是你要查的是分组字段或聚合值;如果后续还要查该班级的最高分、人数、学生名单等,HAVING就不够用了 - 如果原始表里有班级根本没人录入成绩(即该
class_id在students表里无记录),HAVING版本根本查不到它;而嵌套查询配合LEFT JOIN classes可以体现“空班”,这点容易被忽略 -
HAVING写法简洁,但可读性弱——别人一眼看不出你是在筛班级,还是在筛学生
性能和 NULL 处理的实际影响
当数据量大时,嵌套查询可能比 HAVING 多一次临时表物化,但差别通常不大;真正容易出问题的是 NULL 和空班级:
-
AVG(score)遇到全为NULL的班级,返回NULL,而NULL >= 60结果为UNKNOWN,该班级不会出现在结果中——这符合直觉,但若业务要求“零分也算不及格”,就得显式写成COALESCE(AVG(score), 0) >= 60 - 如果表里有大量无效数据(比如
score = -1表示未考试),得先在子查询里WHERE score > 0过滤,否则平均分会失真 - MySQL 8.0+ 支持 CTE,可以用
WITH class_avg AS (...) SELECT * FROM class_avg WHERE ...提高可读性,但本质和子查询一样
嵌套查询本身不难,难的是想清楚“及格”到底指什么:是平均分 ≥ 60,还是至少一半人及格,还是去掉最高最低后的均值?这些语义差异,都会让 SQL 变得完全不同。
相关文章
- 明末渊虚之羽剧情是怎样的 07-03
- 明末渊虚之羽防具有哪些排名 07-02
- 如何获取和平精英皮肤照片 07-02
- 空洞骑士丝之歌如何获取制造金属 07-02
- 鱼骨头螃蟹阵容如何搭配 07-02
- 战魂旅人玩法是什么 07-02