关于sql 中 group by 和 having

时间:2022-04-14 05:56:01

今天看到园里一篇文章(http://www.cnblogs.com/sheldon-lou/p/4881230.html)中面试中有关sql 查询方面的问题,

想想自己从上大学就学习数据库,到后来自己也胡乱的写过一些小SQL,发现每次遇到问题,直接百度,然后Ctrl+C,Ctrl+V,

却也从来没有认真的去想过这个GRUOP BY和HAVING到底是怎么用,或是他们都有些什么用。说来惭愧的很。

创建表(自己瞎写的两个表):

CREATE TABLE    Department (
depID varchar(50) NOT NULL ,
depName varchar (50) NOT NULL
) CREATE TABLE Employee (
empID varchar (50) NOT NULL ,
empName varchar (50) NOT NULL ,
depID varchar (50) NOT NULL ,
empSex varchar (50) NULL ,
empAge int NULL
)

插入数据:

insert into Department(depID,depName) values('','技术部')
insert into Department(depID,depName) values('','流通部')
insert into Department(depID,depName) values('','采编部')
insert into Employee(empID,empName,depID,empSex,empAge) values('e0001','张三','','男',35)
insert into Employee(empID,empName,depID,empSex,empAge) values('e0002','李四','','男',30)
insert into Employee(empID,empName,depID,empSex,empAge) values('e0003','王五','','男',28)
insert into Employee(empID,empName,depID,empSex,empAge) values('e0004','清风','','女',32)
insert into Employee(empID,empName,depID,empSex,empAge) values('e0005','秋月','','女',30)
insert into Employee(empID,empName,depID,empSex,empAge) values('e0001','夏荷','','女',25)

多年的学校生活让我懒得不能再懒了,以下不少内容也是来自于网络,如有累同,勿怪。

1.     GROUP BY :group by将数据行分组,然后用聚组函数返回每一个组的汇总信息。

比如对于人员管理来说:我想查查各个部门多少人?

select a.depName,count(*) from Department a,Employee b
where a.depID=b.depID
group by a.depName

结果

003 采编部 2
001 技术部 2
002 流通部 2

这个是 依据(GROUP BY)部门名称(depName)来分组。

当然,如果这样的话是行不通的:

select a.depName,count(*) from Department a,Employee b
where a.depID=b.depID
group by a.depID 出现这样的错误:列 'a.depName' 在选择列表中无效,因为该列既不包含在聚合函数中,也不包含在 GROUP BY 子句中 所以:
在使用group by 时,有一个规则需要遵守,即出现在select列表中的字段,如果没有在组函数中,那么必须出现在group by 子句中。(select中的字段不可以单独出现,必须出现在group语句中或者在组函数中。)

还要注意一点:

当同时含有 where 子句、group by 子句 、having 子句及聚集函数时,执行顺序如下:

1.执行 where 子句查找符合条件的数据;
2.使用 group by 子句对数据进行分组;
3.对 group by 子句形成的组运行聚集函数计算每一组的值;
4.最后用 having 子句去掉不符合条件的组。

2.    HAVING:

  有人说"限制返回的结果集",但我更喜欢这个解释:"在分组之后过滤数据"
还是例子说话:
select a.depName,count(*) from Department a,Employee b
where a.depID=b.depID
group by a.depName
having a.depName like'采%'

结果也只有一条: 003 采编部 2

当然,如果我想查岁数大于30的如果呢?

select a.depName,count(*) from Department a,Employee b
where a.depID=b.depID
group by a.depName
having b.empAge>30

这个显然是行不通的:

1.分完组后,里面是没有empAge这个字段的,故也不可能按此字段过滤数据。

2.前面提到了,先查数据,再分组,最后过滤。

其实我最想说的是下面这段话(不是我说的):

where:      在分组前进行过滤数据;

group by:  在分组前查询后,先排序再分组;

having:      在分组后进行过滤数据。