MySQL分组后筛选

在SELECT 语句中,使用GROUP BY子句进行分组后,如果需要对分组后的数据进行筛选,可以使用HANING子句指定筛选条件。
语法

select <字段名列表> from <表名> 
[where <查询条件>] 
group by <分组字段列表> 
having <筛选条件>;

HAVING 子句和 WHERE 子句非常相似,都是对数据进行过滤,HAVING 子句支持 WHERE 子句中所有的操作符和语法。
示例:查询各部门clerk的最低工资

mysql> select deptno,job,min(sal) 最低工资
    -> from emp
    -> where job='clerk'
    -> group by deptno,job;
+--------+------------+--------------+
| deptno | job        | 最低工资     |
+--------+------------+--------------+
|     10 | clerk      |         1300 |
|     20 | clerk      |          800 |
|     30 | clerk      |          950 |
+--------+------------+--------------+

mysql> select deptno,job,min(sal) 最低工资
    -> from emp
    -> group by deptno,job
    -> having job='clerk';
+--------+------------+--------------+
| deptno | job        | 最低工资     |
+--------+------------+--------------+
|     10 | clerk      |         1300 |
|     20 | clerk      |          800 |
|     30 | clerk      |          950 |
+--------+------------+--------------+

WHERE与HAVING的区别

  • WHERE 子句主要用于过滤数据行,而 HAVING 子句主要用于过滤分组。
  • WHERE 子句不可以包含聚合函数,HAVING 子句中的条件可以包含聚合函数。
  • HAVING 子句是在数据分组后进行过滤,WHERE 子句会在数据分组前进行过滤,WHERE 子句排除的行不包含在分组中。

示例:查询各部门平均工资大于3000的职位

mysql> select deptno,job,avg(sal)
    -> from emp
    -> where avg(sal)>3000
    -> group by deptno,job;
ERROR 1111 (HY000): Invalid use of group function

mysql> select deptno,job,avg(sal)
    -> from emp
    -> group by deptno,job
    -> having avg(sal)>3000;
+--------+-----------+----------+
| deptno | job       | avg(sal) |
+--------+-----------+----------+
|     10 | persident |     5000 |
+--------+-----------+----------+

SQL语句的执行顺序:

FROM -> ON -> JOIN -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> UNION -> ORDER BY -> LIMIT

WHERE在分组和聚集计算之前筛选行,而HAVING 在分组和聚集之后筛选分组的行,因此WHERE子句不能包含聚集函数。
而HAVING 子句是在SELECT子句前执行,因此一般不能在HAVING 子句中使用select定义的别名。但是MySQL对此作了扩展。在mysql 5.7.5之前的版本,ONLY_FULL_GROUP_BY sql mode默认不开启。在5.7.5或之后的版本默认开启。
如果ONLY_FULL_GROUP_BY sql mode不开启,那么mysql对标准SQL的扩展可以生效:

  • 允许在select、having和order by中使用没有出现在group by中的字段。此时mysql会随机选择没有出现在group by中的字段的值。
  • 允许在having中使用select定义的别名。
    HAVING 子句中的筛选字段必须在SELECT子句中出现:查询各部门manager的平均工资
mysql> select deptno,avg(sal) 平均工资
    -> from emp
    -> group by deptno
    -> having job='manager';
ERROR 1054 (42S22): Unknown column 'job' in 'having clause'

mysql> select deptno,job,avg(sal) 平均工资
    -> from emp
    -> group by deptno,job
    -> having job='manager';
+--------+------------+--------------+
| deptno | job        | 平均工资     |
+--------+------------+--------------+
|     10 | manager    |         2450 |
|     20 | manager    |         2975 |
|     30 | manager    |         2850 |
+--------+------------+--------------+
发布了95 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/kejiayuan0806/article/details/102433264