八、分组查询(group by)

一、概要

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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章