计算机应用

导航

第13周 数据分组统计与子查询

第13周 · 数据分组统计与子查询

上週学了聚合,但只能算"全体的"汇总。这周学 GROUP BY 把数据分组后分别汇总(如每个班各自的平均分),再用 HAVING 筛掉不达标组。另外学子查询——把一个查询塞进另一个查询里,拆解复杂问题。


一、知识点:为什么要分组

AVG(grade) 算的是所有人的平均分。要"每个班的平均分",就得先按班分组,再各组分别聚合——这就是 GROUP BY


二、操作教程:GROUP BY 分组统计

-- 每个学生(sid)选了几门课
SELECT sid, COUNT(*) AS 门数
FROM sc
GROUP BY sid;

结果:

2024001  2
2024002  1
2024003  2

GROUP BY sid 后,SELECT 里只能出现:分组列(sid)聚合函数(COUNT/AVG…)。写别的单列会报错。


三、操作教程:HAVING 筛选分组

分组后想"只要选课≥2门的人",用 HAVING(作用于组,不是行):

SELECT sid, COUNT(*) AS 门数
FROM sc
GROUP BY sid
HAVING COUNT(*) >= 2;

结果只保留 20240012024003


四、知识点:WHERE 与 HAVING 的区别(重点)

WHERE HAVING
作用对象 (分组前筛选) (分组后筛选)
能否用聚合 不能(分组前还没聚合) 能(HAVING COUNT(*)>=2
位置 GROUP BY 之前 GROUP BY 之后

记忆:WHERE 筛掉不要的行 → 再 GROUP BY 分组 → 最后 HAVING 筛掉不要的组

-- 例:先只算有成绩(grade不为空)的记录,再按sid分组,只要门数>=2
SELECT sid, COUNT(*) AS 门数
FROM sc
WHERE grade IS NOT NULL
GROUP BY sid
HAVING COUNT(*) >= 2;

五、知识点:SQL 执行顺序(背下来)

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

理解这个顺序,很多报错就通了:WHERE 不能用聚合(因为聚合在 GROUP BY 之后才产生);SELECT 的别名不能在 WHERE 里用(因为 SELECT 晚于 WHERE)。


六、知识点 + 操作:子查询

子查询 = 一个 SELECT 嵌在另一个 SELECT 里。口诀:先算内层,再算外层

6.1 IN 子查询(返回多行)

查"成绩>90 的学生姓名"——先找出哪些 sid 成绩>90,再去 student 取名字:

SELECT sname FROM student
WHERE sid IN (SELECT sid FROM sc WHERE grade > 90);

内层 (SELECT sid FROM sc WHERE grade > 90) 返回 2024001,外层再取该学号姓名 → 张伟。

6.2 标量子查询(返回单个值)

返回一行一列的子查询,可放在 SELECTWHERE 比较里:

-- 查每个学生成绩,并标出"与最高分差多少"
SELECT sid, grade,
       (SELECT MAX(grade) FROM sc) AS 最高分
FROM sc;

标量子查询必须只返回 1 个值;返回多值会报错,那种情况改用 IN


七、综合实操:作业三题

-- 题1:每个学生选课门数
SELECT sid, COUNT(*) AS 门数 FROM sc GROUP BY sid;

-- 题2:选课≥2门的学生
SELECT sid, COUNT(*) AS 门数 FROM sc GROUP BY sid HAVING COUNT(*) >= 2;

-- 题3:成绩>90的学生姓名(IN 子查询)
SELECT sname FROM student
WHERE sid IN (SELECT sid FROM sc WHERE grade > 90);

八、易混点排查表

现象 解决方法
SELECT 写了非分组列报错 GROUP BY 后只能选分组列或聚合函数
HAVING 用不了聚合 其实能用;不能用聚合的是 WHERE,确认位置
WHERE 里写 COUNT(*) 报错 聚合在分组后才产生,筛选组用 HAVING
子查询报"返回多行" 标量子查询只接受1值;多值改用 IN
子查询结果为空 先单独跑内层确认有数据;再套外层
顺序搞不清 背:FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY

九、小测验(自测)

  1. GROUP BY sid 之后,SELECT 里能随便写 sname 吗?为什么?
  2. WHEREHAVING 的根本区别是什么?查"平均分>80 的班"该用哪个?
  3. 写出 SQL 执行顺序。为什么 WHERE 里不能用聚合函数?
  4. 查"成绩大于90的学生姓名",用 IN 子查询怎么写(先内后外分解)?

【声明】本文由 AI 辅助生成,仅供 MySQL 数据库教学参考,如有疑误以教材为准。

posted on 2026-08-29 10:26  eagle福  阅读(7)  评论(0)    收藏  举报