MySQL聚合函数与数据分组
我们最常需要的是汇总数据而不是把他们实际检索出来
- 确定表中行数(或满足某个条件或包含某个特定值的行数)
- 确定表中行组的和
- 找出表列(或所有行或特定列)的最大值,最小值和平均值
聚集函数是运行在行组上,计算和返回单个值的函数。
求平均值 |
|
统计行的数量 |
|
求最大值 |
|
求最小值 |
|
求累加和 |
AVG,SUM
只用于单个列,为获得多个列的平均值要使用多个AVG,表中列值为null的行不参与计算
要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。
COUNT
- count(*):返回表中行的数量,不管列表中包含NULL值还是非NULL值,distinct不能用于count(*)
- count(列):返回列值非空的行的数量
- count(distinct 列):返回列值非空的、并且列值不重复的行的数量
- count(expr):根据表达式统计数据
select UNIT as '单位', -> COUNT(TO_DAYS(DATE)=TO_DAYS(NOW()) or null) as '今日统计', -> COUNT(YEAR(DATE)=YEAR(NOW()) or null) as '今年统计' -> from v_jjd -> group by JJDW;
MAX、MIN
返回任意列的最大值,最小值(包括文本列),如果统计的列中只有NULL值,那么MAX和MIN就返回NULL
注意
- 每个组函数接收一个参数
- 默认情况下,组函数忽略列值为null的行,不参与计算
- 有时,会使用关键字distinct剔除字段值重复的条数
- 组函数不允许嵌套,例如:count(max(…))
- 组函数的参数可以是列或是函数表达式;
- 一个SELECT子句中可出现多个聚集函数
数据分组
把数据分为多个逻辑组,以便对每个组进行聚集计算
- group by可以包含任意数目得列,这使得能够对分组进行嵌套
- 如果在group by中间套了分组,数据将在最后的分组上汇总,换句话说,建立分组时,所有指定的列都一起计算
- group by中的每个列都必须是检索列或有效的表达式(不能使聚合函数),必须与在select中使用相同的表达式不能使别名
- 除聚集计算语句外,select中的每个列都必须在group by中给出,也就是说:通过select在返回集字段中,这些字段要么就要包含在group by语句后面,作为分组的依据,要么就要被包含在聚合函数中
- 如果分组列中有NULL值,NULL作为一个分组返回,若有多个NULL,他们分为一组返回
- 使用with rollup可以得到分组及分组汇总级别(针对每个分组的值)
sql一个执行过程:先执行的是from负责把数据库的表文件加载到内存中去,WHERE取出符合条件的记录行,生成一张临时表,select读取根据sql中有无group by(没有GROUP BY时,SELECT 会根据后面的字段名称对内存中的一张临时表整列读取,有GROUP BY时,会对内存中的若干临时表分别执行SELECT,而且只取各临时表中的第一条记录,然后再形成新的临时表。这就决定了查询sql使用GROUP BY的场景下,SELECT后面跟的一般是参与分组的字段和聚合函数,否则查询出的数据要是情况而定。另外聚合函数中的字段可以是表中的任意字段,需要注意的是聚合函数会自动忽略空值得到一个结果集,然后根据分组字段,将具有相同分组字段的记录归并成了一条记录(行)。这个时候剩下的那些不存在与group by语句后面作为分组依据的字段就很有可能出现多个值,但是目前一种分组情况只有一条记录(行),一个数据格是无法放入多个数值的,所以这个时候就需要通过一定的处理将这些多值的列转化成单值,然后将其放在对应的数据格中,那么完成这个步骤的就是前面讲到的聚合函数,这也就是为什么这些函数叫聚合函数),然后having对生成的临时表再次过滤,order by对生成的临时表排序,limit取数据个数。
having与where区别
- where过滤指定的行,在分组之前过滤数据,where条件中不能包含聚组函数,使用where条件过滤出特定的行。
- having过滤分组,在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件过滤出特定的组,也可以使用多个分组标准进行分组。
- HAVING可以单独使用而不和GROUP BY配合,如果只有HAVING子句而没有GROUP BY,表中所有的行分为一组
- HAVING子句中可以使用组函数
- HAVING子句中的列,要么出现在一个组函数中,要么出现在GROUP BY子句中(否则出错)
order by与group by
order by | group by |
排序产生的输出 | 分组行,单输出可能不是分组的顺序 |
任意列可使用(甚至是非选择的列) | 只能使用选择列或表达式列,而必须使用每个选择列表达式 |
不一定需要 |
如果与聚合函数一起使用(或表达式列),则必须使用 |
select句子顺序
子句 | 说明 | 是否必须使用 |
select | 要返回的列或表达式 | YES |
from | 从检索数据的表 | 仅在从表中选择数据时 |
where | 行级过滤 | NO |
group by | 分组说明 | 仅在按组计算聚集时使用 |
having | 组级过滤 | NO |
order by | 要输出排序顺序 | NO |
limit | 要检索的行数 | NO |