4.2 数据库分组查询
1、为什么要分组
上一节课我们学习了聚合函数,默认统计的是全表范围的数据。配合上where子句就能缩小统计的范围了,但是这并不能满足我们的要求。比如说我现在想查询每个部门的平均底薪是多少钱,这个就需要对员工记录,按照部门编号去分组了。比如说10部门的员工分成一组,20部门的员工分成另一组,以此类推。根据分组的情况,统计小组内的最大值、最小值、平均值。
2、group by函数
分组的语法是通过group by子句来实现的,它能按照某个字段对记录分组这个字段。值相等的记录就归为一组了。比如说按照deptno字段分组,那么部门编号相同的员工就被编为一组了。
查询每个部门的平均底薪
select
deptno,avg(sal)
from t_emp group by deptno;
3.逐级分组
有的时候仅有大的分组还不够,我们还要在大的分组里边再划分出来小的分组,再执行统计计算。比如说我现在想查看每个部门里边每种职位的人员数量和平均的底薪。首先就要按照部门对员工记录分组的。在部门里边,我们还要按照职务去分组,最后再用select子句里边的聚合函数去统计一下
查询每个部门里,每种职位的人员数量和平均底薪,按照部门编号升序排序
select
deptno,job,count(*),avg(sal)
from t_emp
group by deptno,job
order by deptno;
4. 对SELECT 子句的要求
如果查询语句里边含有group by子句,那么select子句里边的内容就必须遵守一个规定:SELECT子句里边可以包括聚合函数或者group by用作分组的字段,其他的内容,是不可以出现在select子句中的。
比如下面这个sql,sal字段不是聚合函数的分组列也不是聚合函数,前面的deptno,count(*),avg(sal)都是只有一个字段,但是sal字段一个部门有好多,就会出现数据匹配的问题,无法准确匹配
select
deptno,count(*),avg(sal),sal
from t_emp
group by deptno;
5. 对分组结果集再次做汇总计算
WITH ROLLUP子句
看一下select子句里面写的内容,这个部门编号,部门里边的人数,底薪的平均值、最大值,还有最小值,这个结果集里面前三条记录是按照部门去分组,然后统计每个部门里边的人数,还有是底薪的一些情况,因为使用了 WITH ROLLUP 这样的关键字,这个mysql会对这个结果集里边的这个汇总结果,会再统计一下它的汇总值。
比如说这个count(*),按照部门去分组之后,结果就是3个人、5个人和6个人。那么咱们这个 WITH ROLLUP出现以后,就是对这三个结果再次汇总一下,求一下这个总人数,这个总记录的条数就是14
select
deptno,count(*),avg(sal),max(sal),min(sal)
from t_emp
group by deptno with rollup;
6. GROUP_CONCAT函数
那么group_concat函数就可以把分组查询中的非分组字段多条记录合并成一条记录。
关于具体用法可以看一下下面的例子
查询每个部门内底薪超过2000元的人数和员工姓名
select deptno,count(*),group_concat(ename)
from t_emp where sal>2000
group by deptno;
7. 各种子句的查询顺序
首先是from子句,然后是where子句来筛选数据符合条件的记录就留下来交由group by子句来分组分完组了,要用select子句中的聚合函数做汇总计算,order by子句对结果排序的,最后交给limit子句来挑选返回哪些分页的数据。
FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT