《数据库系统》SQL语言之分组查询与分组过滤(理论理解分析+实例练习)
分组查询
SQL可以将检索到的元组按照某一条件进行分类,具有相同条件值的元组划到一个组或一个集合中,同时处理多个组或集合的聚集运算。
 分组的基本语法:group by
EG: 求每一个学生的平均成绩
 按照学号进行分组,学号相同的元组划到一个组中并求平均值。
select Snumber, avg(Score) from SC group by Snumber;
EG: 求每一门课程的平均成绩
 按照课程号进行分组,课程号相同的元组划到一个组中并求平均值。
select Cnumber, avg(Score) from SC group by Cnumber;
分组过滤
聚集函数是不允许用于where子句中的:where子句是对每一元组进行条件过滤,而不是对集合进行条件过滤。(也就是说,where子句处理的对象是每一个元组;聚集函数处理的对象是集合,因此聚集函数不能放于where子句中)
 若要对集合(即分组)进行条件过滤,即满足条件的集合/分组留下,不满足条件的集合/分组剔除,则为 分组过滤。
 having子句,又称为分组过滤子句。需要有group by子句支持。(也就是说,没有group by子句,就没有having子句)
EG: 求不及格课程超过两门的同学的学号
 首先筛选出不及格成绩(where Score < 60),其次将不及格课程成绩按照学号分组(group by Snumber,为一个学生的所有不及格课程成绩单),对这个分组内的个数进行判断(having Count(*) > 2)。
select Snumber from SC where Score < 60 
group by Snumber having Count(*) > 2;
EG: 求有10人以上不及格的课程号
 首先筛选出不及格成绩(where Score < 60),其次将不及格课程成绩按照课程号分组(group by Cnumber,为一个课程的所有不及格课程成绩单),对这个分组内的个数进行判断(having Count(*) > 10)。
select Cnumber from SC where Score < 60
goup by Cnumber having Count(*) > 10;
having子句与where子句的区别
| having子句 | where子句 | |
|---|---|---|
| 作用对象 | 每一分组/集合 | 每一元组 | 
| 条件 | 必须有group by子句 | 
EG: 求有两门以上不及格课程同学的学号以及平均成绩
 ❌错误示例:
select Snumber, avg(Score) from SC
where Score < 60 group by Snumber having count(*) > 2;
求解的为:
 where子句得到的为“有两门以上不及格课程同学的集合”
 则select选择后得到他们的学号和这些不及格课程的平均成绩。
⭕正确示例:
select Snumber, avg(Score) from SC
where Snumber in(Select Snumber from SCwhere Score < 60group by Snumber having count(*) > 2)
group by Snumber;
求解的为:
 嵌套select:筛选出不及格课程数大于2的所有学生的学号
 外层select:则根据满足条件的学生学号进行分组,求他们所有课程的平均成绩。
本文以哈尔滨工业大学战德臣老师讲授《数据库系统》为系统依据整理得出。具体可前往链接【哈工大】数据库系统 战德臣(全23讲)-哔哩哔哩
