包含聚集、group by或having子句的查询的含义可通过以下操作顺序来定义:
(1)最先根据from子句来计算出一个关系。
(2)如果出现了where子句,where子句中的谓词将应用到from子句的结果关系上。
(3)如果出现了group by子句,满足where谓词的元组通过group by子句形成分组,在每个分组上都要进行指定的聚集计算。如果没有group by子句,满足where谓词的整个元组集被当做一个分组。(允许对多个关系一起进行分组,或者先将多个关系进行连接。)
(4)如果出现了having子句,它将应用于每个分组上:不满足having子句谓词的分组将被抛弃。
(5)select子句利用剩下的分组产生出查询结果中的元组,即在每个分组上应用聚集函数来得到结果元组。注:需要保证出现在select语句中但没有被聚集的属性只能是出现在group by子句(准确来说是形成分组的属性)中的那些属性。
考虑以下instructor关系的元组:
ID | name | dept_name | salary |
10101 | Srinivasan | Comp.Sci. | 65000 |
12121 | Wu | Finance | 90000 |
15151 | Mozart | Music | 40000 |
22222 | Einstein | Physics | 95000 |
32343 | El Said | History | 60000 |
33456 | Gold | Physics | 87000 |
45565 | Katz | Comp.Sci. | 75000 |
58583 | Califieri | History | 62000 |
76543 | Singh | Finance | 80000 |
76766 | Crick | Biology | 72000 |
83821 | Brandt | Comp.Sci. | 92000 |
98345 | Kim | Elec.Eng. | 80000 |
以及以下查询语句:
select dept_name, avg(salary) as avg_salary_below_70000
from instructor
where salary < 70000
group by dept_name
having avg(salary) > 42000;
(1)首先从from子句确定查询关系为instructor;
(2)根据where子句筛选出salary < 70000的元组:
ID | name | dept_name | salary |
10101 | Srinivasan | Comp.Sci. | 65000 |
15151 | Mozart | Music | 40000 |
32343 | El Said | History | 60000 |
58583 | Califieri | History | 62000 |
(3)根据group by子句中的dept_name属性形成分组:
ID | name | dept_name | salary |
10101 | Srinivasan | Comp.Sci. | 65000 |
32343 | El Said | History | 60000 |
58583 | Califieri | History | 62000 |
15151 | Mozart | Music | 40000 |
(4)根据having子句抛弃avg(salary) <= 42000的分组:
ID | name | dept_name | salary |
10101 | Srinivasan | Comp.Sci. | 65000 |
32343 | El Said | History | 60000 |
58583 | Califieri | History | 62000 |
(5)对剩下的分组进行select得到查询结果:
dept_name | avg_salary_below_70000 |
Comp.Sci. | 65000 |
History | 61000 |
注:如果select语句中查询没有聚集但不出现在group by子句的属性则会出错,例如
select dept_name, ID, avg(salary) as avg_salary_below_70000
from instructor
where salary < 70000
group by dept_name
having avg(salary) > 42000;
在一个特定的分组(通过dept_name定义)中的每位教师都有一个不同的ID,既然分组只输出一个元组,那就无法确定选哪个ID值作为输出。其结果是,SQL不允许出现这样的情况。