3.7.3 having子句

3.7.3 having子句

有时候,对分组限定条件比对元组限定条件更有用。例如,我们也许只对教师平均工资超过42000美元的系感兴趣。该条件并不针对单个元组,而是针对group by子句构成的分组。为表达这样的查询,我们使用SQLhaving子句。

having子句对分组起作用

having子句中的谓词在形成分组后才起作用,因此可以使用聚集函数。

SQL查询 找出教师平均工资超过42000美元的系

我们用SQL表达该查询如下:

1
2
3
4
select dept_name, avg(salary) as avg_salary
from instructor
group by dept_name
having avg(salary)>42000;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> select dept_name, avg(salary) as avg_salary
from instructor
group by dept_name
having avg(salary)>42000;
+------------+--------------+
| dept_name | avg_salary |
+------------+--------------+
| Biology | 72000 |
| Comp. Sci. | 77333.333333 |
| Elec. Eng. | 80000 |
| Finance | 85000 |
| History | 61000 |
| Physics | 91000 |
+------------+--------------+
6 rows in set

having子句中的没有被聚集的属性必须出现在group by子句中

select子句的情况类似,任何出现在having子句中,但没有被聚集的属性必须出现在group by子句中,否则查询就被当成是错误的。

查询子句顺序: 先from 再where 然后 group by 接着having 最后select 聚集

包含聚集group byhaving子句的查询的含义可通过下述操作序列来定义:

  1. 与不带聚集的查询情况类似,最先根据from子句来计算出一个关系。
  2. 如果出现了where子句, where子句中的谓词将应用到from子句的结果关系上。
  3. 如果出现了group by子句,满足where谓词的元组通过group by子句形成分组。如果没有group by子句,满足where谓词的整个元组集被当作一个分组
  4. 如果出现了having子句,它将应用到每个分组上;不满足having子句谓词的分组将被抛弃。
  5. select子句利用剩下的分组产生出查询结果中的元组,即在每个分组上应用聚集函数来得到单个结果元组。

SQL查询 对于在2009年讲授的每个课程段,如果该课程段有至少2名学生选课,找出选修该课程段的所有学生的总学分(tot_cred)平均值

为了说明在同一个查询中同时使用having子句和where子句的情况,我们考虑查询”对于在2009年讲授的每个课程段,如果该课程段有至少2名学生选课,找出选修该课程段的所有学生的总学分(tot_cred)平均值“。

1
2
3
4
5
select course_id, semester, year, sec_id, avg(tot_cred)
from takes natural join student
where year=2009
group by course_id, semester, year, sec_id
having count(ID)>=2;
1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select course_id, semester, year, sec_id, avg(tot_cred)
from takes natural join student
where year=2009
group by course_id, semester, year, sec_id
having count(ID)>=2;
+-----------+----------+------+--------+---------------+
| course_id | semester | year | sec_id | avg(tot_cred) |
+-----------+----------+------+--------+---------------+
| CS-101 | Fall | 2009 | 1 | 65 |
| CS-190 | Spring | 2009 | 2 | 43 |
| CS-347 | Fall | 2009 | 1 | 67 |
+-----------+----------+------+--------+---------------+
3 rows in set