一、概要
Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”。它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理。 如果在查询的过程中需要按某一列的值进行分组,以统计该组内数据的信息时,就要使用group by子句。不管select是否使用了where子句都可以使用group by子句。
group by子句一定要与聚合函数结合使用,否则没有意义。
二、语法格式
SELECT [DISTINCT] * | 列名称 [别名] ,... | 聚合函数
FROM 表名
[WHERE 条件]
[GROUP BY 分组字段, 分组字段, ...]
[WITH ROLLUP]]
[HAVING where_contition]
[ORDER BY 字段 [ASC | DESC] , 字段 [ASC | DESC] ,...]
参数进行以下说明:
- 聚合函数, sum(求和)、 count(*)(记录数)、 max(最大值)、 min(最小值)、avg(平均值)。
- GROUP BY 关键字表示要进行分类聚合的字段。
- WITH ROLLUP 是可选语法, 表明是否对分类聚合后的结果进行再汇总。
- HAVING 关键字表示对分类后的结果再进行条件的过滤。
注意
: having 和 where 的区别在于having 是对聚合后的结果进行条件的过滤
, 而 where 是在聚合前就对记录进行过滤
, 如果逻辑允许, 我们尽可能用 where 先过滤记录, 这样因为结果集减小, 将对聚合的效率大大提高, 最后再根据逻辑看是否用 having 进行再过滤。
三、数据
创建一个名称为 emp 的表。 表中包括 3 个字段, ename(姓名), hiredate(雇用日期)、sal(薪水), deptno (部门):
mysql> create table emp(ename varchar(10),hiredate date,sal decimal(10,2),deptno int(2));
Query OK, 0 rows affected (0.02 sec)
插入数据:
+--------+------------+---------+--------+
| ename | hiredate | sal | deptno |
+--------+------------+---------+--------+
| bjguan | 2004-04-02 | 5000.00 | 1 |
| zzx | 2000-01-01 | 2000.00 | 1 |
| lisa | 2003-02-01 | 4000.00 | 2 |
| bzshen | 2005-04-01 | 4000.00 | 3 |
+--------+------------+---------+--------+
四、示例代码
查询公司总人数
mysql> select count(*) from emp;
+----------+
| count(*) |
+----------+
| 4 |
+----------+
1 row in set (0.00 sec)
统计各个部门的人数:
mysql> select deptno,count(*) from emp group by deptno;
+--------+----------+
| deptno | count(*) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
+--------+----------+
3 rows in set (0.00 sec)
显示每个部门员工的平均工资
mysql> SELECT deptno ,AVG(sal) 平均工资
> FROM emp GROUP BY deptno;
+--------+----------+
| deptno | 平均工资 |
+--------+----------+
| 1 | 3500.00 |
| 2 | 4000.00 |
| 3 |4000.00 |
+--------+----------+
3 rows in set (0.00 sec)
五、注意事项
(1):
GROUP BY后不可以接列的别名(根据执行顺序分析就知道了)
SELECT deptno dn ,AVG(sal)
FROM emp
GROUP BY dn; --错误
(2):
GROUP BY 后不能接数字
SELECT deptno dn ,AVG(sal)
FROM emp
GROUP BY 1; --错误
(3):
GROUP BY 后不可以接select后没有的列名
SELECT deptno dn ,AVG(sal)
FROM emp
GROUP BY job; --错误
(4):
如果一个SELECT中使用了聚合函数,任何不在聚合函数中的列(表达式)必须要在GROUP BY中
SELECT job ,deptno dn ,AVG(sal)
FROM emp
GROUP BY job; --deptno列group by 后面没有,使用会报错
(3)和(4)总结为一句话:
1、在select中出现的列名必须在group by 中出现,否则,其他列名只能在聚合函数中使用;而在group by 中出现的字段不一定要在select中出现
group by之前可以使用where过滤数据,因为where是在分组之前起作用的
六、使用HAVING过滤分组
1、作用:在分组之后再过滤掉不符合条件的分组
2、与where的区别
相同作用——都是根据条件过滤数据;
不同的是where是在分组之前过滤数据,having是分组之后过滤分组数据。
原则:能在where里过滤的数据就不要在having里面去过滤
3、示例代码
统计人数大于 1 人的部门:
mysql> select deptno,count(*) from emp group by deptno having count(*)>1;
+--------+----------+
| deptno | count(*) |
+--------+----------+
| 1 | 2 |
+--------+----------+
1 row in set (0.00 sec)
七、分类聚合后再汇总WITH ROLLUP
既要统计各部门人数, 又要统计总人数:
mysql> select deptno,count(1) from emp group by deptno with rollup;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| NULL | 4 | ————汇总
+--------+----------+
4 rows in set (0.00 sec)
我们可以使用 coalesce 来设置一个可以取代 NUll 的名称
coalesce 语法:
COALESCE(value,…)是一个可变参函数,可以使用多个参数。
作用:接受多个参数,返回第一个不为NULL的参数,如果所有参数都为NULL,此函数返回NULL;当它使用2个参数时,和IFNULL函数作用相同。
select coalesce(null,2,3); // Return 2
select coalesce(null,null,3); // Return 3
select coalesce(1,2,3); // Return 1
以下实例中如果deptno 为空,我们使用总数代替:
mysql> select coalesce(deptno ,“总数”),count(1) from emp group by deptno with rollup;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| 总数| 4 |
+--------+----------+
4 rows in set (0.00 sec)