3.7.3 分组查询
本课核心知识点整理
分组查询为什么更复杂
普通查询处理的是“行级筛选与列级输出”,分组查询多了一层:先把记录按某些列分成组,再对每组做统计。字幕中特别强调,分组后的条件筛选用 HAVING,不是 WHERE。
典型结构:
sql
SELECT 分组列, 聚合函数
FROM 表
WHERE 分组前的行条件
GROUP BY 分组列
HAVING 分组后的组条件
ORDER BY 排序列 ASC|DESC;常见聚合函数
| 函数 | 作用 | 常见考法 |
|---|---|---|
SUM | 求和 | 供应零件数量总和 |
AVG | 求平均 | 平均成绩、平均库存 |
MAX | 最大值 | 最高分、最大库存 |
MIN | 最小值 | 最低分、最小库存 |
COUNT | 计数 | 记录条数或不同对象个数 |
COUNT 要特别区分:
sql
COUNT(项目号)
COUNT(DISTINCT 项目号)前者统计项目号出现的记录条数;后者统计不同项目的个数。若一个项目下有多条零件供应记录,COUNT(项目号) 可能把同一个项目算多次,而 COUNT(DISTINCT 项目号) 才是项目种类数。
WHERE 与 HAVING
| 子句 | 发生时机 | 能否直接使用聚合函数 | 示例 |
|---|---|---|---|
WHERE | 分组前 | 通常不能 | WHERE 状态='有效' |
GROUP BY | 按列形成组 | 不涉及条件 | GROUP BY 供应商号 |
HAVING | 分组后 | 可以 | HAVING COUNT(DISTINCT 项目号) >= 3 |
题干如果说“筛选选课门数大于 3 的学生”“至少供应 3 个项目的供应商”,条件依赖统计结果,应放在 HAVING。
课程例子:至少供应三个项目的供应商
题干要求“查询至少供应了三个项目的供应商,输出供应商号和供应零件数总和,并按供应商号降序排序”。数据通常来自三元联系转换后的独立关系,例如:
sql
SPP(供应商号, 项目号, 零件号, 数量)查询对象不是供应商表、项目表或零件表单独任意一个,而是记录“供应商-项目-零件”供应事实的联系表。
sql
SELECT 供应商号, SUM(数量) AS 供应零件数总和
FROM SPP
GROUP BY 供应商号
HAVING COUNT(DISTINCT 项目号) >= 3
ORDER BY 供应商号 DESC;这里使用 COUNT(DISTINCT 项目号),因为要求的是“供应了几个不同项目”,不是供应记录条数。一个供应商可能给同一项目供应多种零件,若不用 DISTINCT 会把一个项目重复计数。
与三元联系的衔接
分组查询题可能先考 E-R 判断,再考 SQL。比如供应商、项目、零件之间是三元多对多联系,转换后形成独立联系关系 SPP。统计供应商供应项目数时,应从这个联系关系查,而不是从某个实体表查。
这类综合题的难点不是语法本身,而是先选对查询对象。
做题路线
- 判断是否需要聚合:出现“总数、平均、至少几个、每个部门/课程/供应商”时考虑分组。
- 确定分组列:题干说“按谁统计”,谁通常就是
GROUP BY。 - 分清筛选时机:明细行条件用
WHERE,统计结果条件用HAVING。 COUNT题仔细看是记录条数还是不同对象个数,必要时用DISTINCT。- 输出排序用
ORDER BY,升序ASC可省略,降序写DESC。
例题
按“部门”统计每个部门员工人数,应使用:
筛选“人数大于 10 的部门”这类分组后条件,应使用:
自查要点
- WHERE 和 HAVING 的区别是什么?
- GROUP BY 后 SELECT 中能直接出现哪些列?
- 常见聚合函数有哪些?