mysql聚合函数有:1、avg(),适用于数值类型的字段或变量,不含null;2、sum(),适用于数值类型的字段或变量,不含null;3、max(),适用于数值类型、字符串类型、日期时间类型的字段或变量,不含null;4、min(),适用于数值类型、字符串类型、日期时间类型的字段或变量,不含null;5、count(),计算指定字段在查询结构中出现的个数,不含null等等。
本教程操作系统:windows10系统、mysql 8.0版本、dell g3电脑。
1. 聚合函数介绍
什么是聚合函数
聚合函数作用于一组数据,并对一组数据返回一个值。
5大常见聚合函数类型
1、avg() :只适用于数值类型的字段或变量。不包含null值
2、sum() :只适用于数值类型的字段或变量。不包含null值
3、max() :适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含null值
4、min() :适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含null值
5、count() :计算指定字段在查询结构中出现的个数(不包含null值)
2. group by
2.1 基本使用
可以使用group by子句将表中的数据分成若干组
select column, group_function(column)from table[wherecondition][group bygroup_by_expression][order bycolumn];
明确:where一定放在from后面
在select列表中所有未包含在组函数中的列都应该包含在 group by子句中
select department_id, avg(salary)from employeesgroup by department_id ;
包含在 group by 子句中的列不必包含在select 列表中
select avg(salary)from employeesgroup by department_id ;
2.2 使用多个列分组
#需求:查询各个department_id,job_id的平均工资select department_id dept_id, job_id, sum(salary)from employeesgroup by department_id, job_id ;
2.3 group by中使用with rollup
使用with rollup关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所有记录的总和,即统计记录数量。
select department_id,avg(salary)from employeeswhere department_id > 80group by department_id with rollup;
注意:当使用rollup时,不能同时使用order by子句进行结果排序,即rollup和order by是互相排斥的。
3. having
3.1 基本使用
过滤分组:having子句
1、行已经被分组。
2、使用了聚合函数。
3、满足having 子句中条件的分组将被显示。
4、having 不能单独使用,必须要跟 group by 一起使用。
select department_id, max(salary)from employeesgroup by department_idhaving max(salary)>10000 ;
非法使用聚合函数 : 不能在 where 子句中使用聚合函数 如下:
select department_id, avg(salary)from employeeswhere avg(salary) > 8000group by department_id;
3.2 where和having的对比
区别1:where 可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件;having 必须要与 group by 配合使用,可以把分组计算的函数和分组字段作为筛选条件。
这决定了,在需要对数据进行分组统计的时候,having 可以完成 where 不能完成的任务。这是因为,在查询语法结构中,where 在 group by 之前,所以无法对分组结果进行筛选。having 在 group by 之后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 where 无法完成的。另外,where排除的记录不再包括在分组中。
区别2:如果需要通过连接从关联表中获取需要的数据,where 是先筛选后连接,而 having 是先连接后筛选。 这一点,就决定了在关联查询中,where 比 having 更高效。因为 where 可以先筛选,用一个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。having 则需要先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用的资源就比较多,执行效率也较低。
优点缺点
where 先筛选数据再关联,执行效率高 不能使用分组中的计算函数进行筛选
having 可以使用分组中的计算函数 在最后的结果集中进行筛选,执行效率较低
开发中的选择:
where 和 having 也不是互相排斥的,我们可以在一个查询里面同时使用 where 和 having。包含分组统计函数的条件用 having,普通条件用 where。这样,我们就既利用了 where 条件的高效快速,又发挥了 having 可以使用包含分组统计函数的查询条件的优点。当数据量特别大的时候,运行效率会有很大的差别。
4. select的执行过程
4.1 查询的结构
#方式1:sql92语法select ...,....,...from ...,...,....where 多表的连接条件and 不包含组函数的过滤条件group by ...,...having 包含组函数的过滤条件order by ... asc/desclimit ...,...#方式2:sql99语法select ...,....,...from ... join ... on 多表的连接条件join ...on ...where 不包含组函数的过滤条件and/or 不包含组函数的过滤条件group by ...,...having 包含组函数的过滤条件order by ... asc/desclimit ...,...#其中:#(1)from:从哪些表中筛选#(2)on:关联多表查询时,去除笛卡尔积#(3)where:从表中筛选的条件#(4)group by:分组依据#(5)having:在统计结果中再次筛选#(6)order by:排序#(7)limit:分页
4.2 select执行顺序
你需要记住 select 查询时的两个顺序:
1. 关键字的顺序是不能颠倒的:
select ... from ... where ... group by ... having ... order by ... limit...
2.select 语句的执行顺序(在 mysql 和 oracle 中,select 执行顺序基本相同):
from -> where -> group by -> having -> select 的字段 -> distinct -> order by -> limit1
比如你写了一个 sql 语句,那么它的关键字顺序和执行顺序是下面这样的:
select distinct player_id, player_name, count(*) as num # 顺序 5from player join team on player.team_id = team.team_id # 顺序 1where height > 1.80 # 顺序 2group by player.team_id # 顺序 3having num > 2 # 顺序 4order by num desc # 顺序 6limit 2 # 顺序 7
在 select 语句执行这些步骤的时候,每个步骤都会产生一个虚拟表,然后将这个虚拟表传入下一个步骤中作为输入。需要注意的是,这些步骤隐含在 sql 的执行过程中,对于我们来说是不可见的。
4.3 sql 的执行原理
select 是先执行 from 这一步的。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:
1、首先先通过 cross join 求笛卡尔积,相当于得到虚拟表 vt(virtual table)1-1;
2、通过 on 进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2;
3、添加外部行。如果我们使用的是左连接、右连接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3。
当然如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到是我们的原始数据。
当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1,就可以在此基础上再进行 where 阶段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2。
然后进入第三步和第四步,也就是 group 和 having 阶段。在这个阶段中,实际上是在虚拟表 vt2 的基础上进行分组和分组过滤,得到中间的虚拟表 vt3 和 vt4。
当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 select 和 distinct 阶段。
首先在 select 阶段会提取想要的字段,然后在 distinct 阶段过滤掉重复的行,分别得到中间的虚拟表 vt5-1 和 vt5-2。
当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 order by 阶段,得到虚拟表 vt6。
最后在 vt6 的基础上,取出指定行的记录,也就是 limit 阶段,得到最终的结果,对应的是虚拟表 vt7。
当然我们在写 select 语句的时候,不一定存在所有的关键字,相应的阶段就会省略。
同时因为 sql 是一门类似英语的结构化查询语言,所以我们在写 select 语句的时候,还要注意相应的关键字顺序,所谓底层运行的原理,就是我们刚才讲到的执行顺序。
5.课后练习
#2.查询公司员工工资的最大值,最小值,平均值,总和select max(salary),min(salary),avg(salary),sum(salary)from employees;#3.查询各job_id的员工工资的最大值,最小值,平均值,总和 select job_id,max(salary),min(salary),avg(salary),sum(salary)from employeesgroup by job_id;#4.选择具有各个job_id的员工人数 select job_id,count(*)from employeesgroup by job_id;# 5.查询员工最高工资和最低工资的差距(difference) select max(salary),min(salary),max(salary) - min(salary) as differencefrom employees;# 6.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内select manager_id,min(salary)from employeeswhere manager_id is not nullgroup by manager_idhaving min(salary) >= 6000;# 7.查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序select d.department_name,d.location_id,count(employee_id),avg(salary) avg_salfrom departments d left join employees eon d.department_id = e.department_idgroup by department_name,location_idorder by avg_sal desc;# 8.查询每个工种、每个部门的部门名、工种名和最低工资select department_name,job_id,min(salary)from departments d left join employees e on e.`department_id` = d.`department_id` group by department_name,job_id
以上就是mysql聚合函数有哪些的详细内容。
