一. MySQL的分组语句
MySQL中除了简单的查询之后,还常常使用到分组统计,如统计每一个部门有多少个员工, 每一个部门的员工最大年龄是多少, 最大工资是多少 等,分组中常常会与聚合函数一起使用,来进行统计。 分组时, 要用到 group by 命令。
select 列名1,聚合函数(列名1) from 表名 where 条件语句 group by 列名1;
- 分组时,可以分为 单字段分组和多字段分组, 通常使用单字段分组就够了。
- 所使用的仍然是 yuejl 数据库的 user 表。
二. MySQL的单字段分组
- MySQL 单字段分组使用时,通常与以下几种常见的用法:
分组函数单独使用
分组函数与聚合函数一起使用
分组函数与 having 一起使用
分组函数与 where和having 一起使用
分组函数与with rollup 一起使用
- 下面,针对这五种情况,分别进行分析。
二.一 分组函数单独使用
- 类似于 mysql 中的去重 distinct 功能。
- 使用 group by 命令:
select 列名1 from 表名 group by 列名1;
- 如 按照部门进行分组 查询
select deptId from user group by deptId;
- 注意,这个时候,是不能再查询其他的非聚集函数的,只能查询分组的 deptId 字段。
- 如 按照 deptId 进行分组,再查询 age 字段时:
select deptId,age from user group by deptId;
Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘yuejl.user.age’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
- 可以将 age 用聚集函数括起来, 就是第二种用法。
二.二 分组函数与聚合函数一起使用
- 所用命令:
select 列名1, 聚合函数(列名) from 表名 group by 列名1;
- 如 查询每个部门的 员工的最大年龄和员工的最小年龄
select deptId,max(age) as maxAge ,min(age) as minAge from user group by deptId;
二.三 分组函数与 having 一起使用
- 在分组之后,对分组的信息进行筛选。
- 所用命令:
select 列名1,聚合函数(列名) from 表名 group by 列名1 having 条件;
- 其中,having 后面的条件,只能跟 列名1进行筛选,或者是按照 聚合函数进行筛选, 即只能按照select 查询的字段进行筛选,不能用其他的字段进行选择。 可以拼接筛选
二.三.一 用分组字段进行筛选
- 如查询一下,各个部门的最大年龄和最小年龄,且部门编号为1 的部门信息。
select deptId,max(age) as maxAge,min(age) as minAge from user group by deptId having deptId=1;
- 只查询出部门编号为1 的信息,其余的部门信息不查询出来。
二.三.二 用聚合函数进行筛选
- 如查询一下,各个部门的最大年龄和最小年龄,且 最小年龄必须要大于23 .
select deptId,max(age) as maxAge,min(age) as minAge from user group by deptId having minAge>23;
- id=1和id=3的部门信息,最小年龄为23,不符合条件,只有id=2的部门才符合条件,为24.
二.三.三 用分组字段和聚合函数进行联合筛选
- 如 查询各个部门的最大年龄和最小年龄, 且最小年龄必须是大于23,并且只查询id=1的部门。
select deptId,max(age) as maxAge,min(age) as minAge from user group by deptId having minAge>23 and deptId=1;
- 不存在这样的数据。
二.三.四 用其他的字段,如age 进行筛选一下 (举例 错误案例)
select deptId,max(age) as maxAge,min(age) as minAge from user group by deptId having age>18;
ERROR 1054 (42S22): Unknown column ‘age’ in ‘having clause’
- 分组之后,是没有 age 字段的,是无法进行筛选的。
- 可以用where 语句,在分组之前进行筛选, 即第四种形式。
二.四 分组函数与 where和having 一起使用
select 列名1,聚集函数(列名) from 表名 where 表中所有列的条件都可以 group by 列名1 [having 筛选条件]
- 其中,having 语句,可以要也可以不要, 先进行where 语句的筛选之后,再对筛选的结果进行分组。
二.四.一 不要having的,只保留where 语句
如只查询部门编号为2,3的 部门的最大年龄和最小年龄。
select deptId,max(age) as maxAge,min(age) as minAge from user where deptId=2 or deptId=3 group by deptId;
- 会先进行where 语句进行筛选,再分组。
二.四.二 既有where 语句,又有having 语句的
- 如 只查询部门编号为2,3的部门的最大年龄和最小年龄,且最小年龄必须要大于23.
select deptId,max(age) as maxAge,min(age) as minAge from user where deptId=2 or deptId=3 group by deptId having minAge>23;
- 只查询出 id=2的信息。
- 其中, where 语句的筛选条件,用于分组前,筛选条件为整个表中的列,
- having语句的筛选条件,用于分组后,筛选条件只能是select里面的列。
二.五 分组函数与 with rollup 一起使用
select 列名1,聚集函数(列名) from 表名 where 表中所有列的条件都可以 group by 列名1 roll up [having 筛选条件] ;
- 查询时,对分组查询后的数据,进行一次汇总。
- 如,如只查询部门编号为2,3的 部门的年龄之和。 加上roll up 的效果。
select deptId,sum(age) as sumAge from user where deptId=2 or deptId=3 group by deptId with rollup;
- 24+46=70.
三.多字段分组
select 列名1,列名2,聚集函数(列名) from 表名 where 条件筛选 group by 列名1,列名2 [having 筛选条件]
- 多字段分组,与单字段分组基本是相同的,用法也是相同的。
- 如 按照部门的编号和性别进行分组查询,最大的年龄和最小的年龄。
select deptId,sex,max(age),min(age) from user group by deptId,sex;
- 部门编号为2和3的,只有男性员工,没有女性员工。所以并不是 3*2=6 种情况,而是 3 * 2-2=4 种。
- 关于多字段分组时,与 having,where的关联用法,老蝴蝶就不讲解了,与单字段基本相同。