专栏首页SQL实现MySQL 中 WHERE 和 HAVING 的区别

MySQL 中 WHERE 和 HAVING 的区别

在 MySQL 中,WHERE 子句和 HAVING 子句都有过滤的作用,它们有什么区别呢?

mysql> SELECT * FROM employees HAVING emp_no = 10001;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  10001 | 1953-09-02 | Georgi     | Facello   | M      | 1986-06-26 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.09 sec)

单从结果来看,WHERE 能做的,HAVING 也能做。

实际上,WHERE 子句和 HAVING 子句的区别还蛮大。

从功能上说,WHERE 用于过滤行,而 HAVING 用来过滤分组。WHERE 在数据分组前进行过滤,即 WHERE 过滤掉的数据不包含在分组中,HAVING 在数据分组后才过滤。

在性能方面,如果要过滤的字段上有索引,并且条件满足走索引的规则,放在 WHERE 子句中可以走索引,而放在 HAVING 子句中不能走索引。

请看例子:

mysql> EXPLAIN SELECT * FROM employees WHERE emp_no = 10001;
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | employees | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)



mysql> EXPLAIN SELECT * FROM employees HAVING emp_no = 10001;
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows   | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
|  1 | SIMPLE      | employees | ALL  | NULL          | NULL | NULL    | NULL | 299290 | NULL  |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------+
1 row in set (0.00 sec)

可以看到,条件 emp_no = 10001 在 WHERE 子句中,执行计划显示用到了主键,而条件在 HAVING 子句中,执行计划显示的是全表扫描。

即使字段上没有索引,在执行聚合操作时,当表的数据量比较大,从执行速度方面也能看出两者的区别。

employees 表总共有 30w 条数据,表的部分数据如下:

mysql> SELECT * FROM employees LIMIT 10;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  10001 | 1953-09-02 | Georgi     | Facello   | M      | 1986-06-26 |
|  10002 | 1964-06-02 | Bezalel    | Simmel    | F      | 1985-11-21 |
|  10003 | 1959-12-03 | Parto      | Bamford   | M      | 1986-08-28 |
|  10004 | 1954-05-01 | Chirstian  | Koblick   | M      | 1986-12-01 |
|  10005 | 1955-01-21 | Kyoichi    | Maliniak  | M      | 1989-09-12 |
|  10006 | 1953-04-20 | Anneke     | Preusig   | F      | 1989-06-02 |
|  10007 | 1957-05-23 | Tzvetan    | Zielinski | F      | 1989-02-10 |
|  10008 | 1958-02-19 | Saniya     | Kalloufi  | M      | 1994-09-15 |
|  10009 | 1952-04-19 | Sumant     | Peac      | F      | 1985-02-18 |
|  10010 | 1963-06-01 | Duangkaew  | Piveteau  | F      | 1989-08-24 |
+--------+------------+------------+-----------+--------+------------+
10 rows in set (0.00 sec)

在 WHERE 子句中指定条件明显比在 HAVING 子句中执行速度快。

mysql> SELECT
    ->   last_name,
    ->   COUNT(*) AS cnt
    -> FROM
    ->   employees
    -> WHERE last_name = 'Facello'
    -> GROUP BY last_name ;
+-----------+-----+
| last_name | cnt |
+-----------+-----+
| Facello   | 186 |
+-----------+-----+
1 row in set (0.05 sec)


mysql> SELECT
    ->   last_name,
    ->   COUNT(*) AS cnt
    -> FROM
    ->   employees
    -> GROUP BY last_name
    -> HAVING last_name = 'Facello';
+-----------+-----+
| last_name | cnt |
+-----------+-----+
| Facello   | 186 |
+-----------+-----+
1 row in set (0.26 sec)

关于 WHERE 子句和 HAVING 子句的区别,在《MySQL 必知必会》和《SQL 基础教程》里边都有介绍,《SQL 基础教程》介绍得更加详细。

本文分享自微信公众号 - SQL实现(gh_684ee9235a26),作者:zero

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-02-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MySQL 中 having 和 where 的区别

    如需转载,请注明:https://www.cnblogs.com/zhuchenglin/p/9750882.html

    lin_zone
  • sql语句中where与having的区别

    Where 是一个约束声明,使用Where约束来自数据库的数据,Where是在结果返回之前起作用的,Where中不能使用聚合函数。 Having是一个过滤声明...

    跑马溜溜的球
  • left/right join中on和where的区别

    开发同学提了个问题,如下两种left join中on和where条件的写法是否等价?

    bisal
  • 数据库基础使用

    java攻城狮
  • 玩转Mysql系列 - 第8篇:分组查询详解(group by & having)

    where是在分组(聚合)前对记录进行筛选,而having是在分组结束后的结果里筛选,最后返回整个sql的查询结果。

    路人甲Java
  • 数据库MySQL-查询语句

    dual表是一个伪表。在有些特定情况下,没有具体的表的参与,但是为了保证select语句的完整又必须要一个表名,这时候就使用伪表。

    cwl_java
  • mysql使用总结

    create database sina default character set utf8mb4 collate utf8mb4_unicode_ci; ...

    pydata
  • MySQL最常用分组聚合函数

      1)当使用组函数的select语句中没有group by子句时,中间结果集中的所有行自动形成一组,然后计算组函数;

    码农编程进阶笔记
  • MySQL(五)汇总和分组数据

    工作中经常需要汇总数据而不是将它们全部检索出来(实际数据本身:返回实际数据是对时间和处理资源的浪费),这种类型的检索有以下特点:

    allsmallpig
  • SQL语句中 where 和 on 的区别

    最近面试时候碰到一道题,关于数据库左连接和内连接中and和where的区别,网上看了看资料,加深一下印象,大家也可以看看。

    浩Coding
  • MySQL问题集锦

    (1)SELECT子句是必选的,其它子句如WHERE子句、GROUP BY子句等是可选的。

    Dabelv
  • day04_MySQL学习笔记_01

    数据库(DataBase,DB):指长期保存在计算机的存储设备上,按照一定规则组织起来,可以被各种用户或应用共享的数据集合。(文件系统)

    黑泽君
  • 大厂高频面试题:如何实现 MySQL 删除重复记录并且只保留一条?

    最近在做题库系统,由于在题库中添加了重复的试题,所以需要查询出重复的试题,并且删除掉重复的试题只保留其中1条,以保证考试的时候抽不到重复的题。

    程序员白楠楠
  • Vc数据库编程基础MySql数据库的表查询功能

      不管是任何数据库.都会有查询功能.而且是很重要的功能.上一讲知识简单的讲解了表的查询所有.

    IBinary
  • Mysql 必知必会(一)

    select prod_price,prod_name from products where prod_price = 2.50;

    Jacob丶
  • Python数据库操作 DQL-MySQL数据库查询sql#学习猿地

    + where子句类似程序语言中if条件,根据mysql表中的字段值来进行数据的过滤

    学习猿地
  • Python数据库操作 DQL-MySQL数据库查询sql#学习猿地

    + where子句类似程序语言中if条件,根据mysql表中的字段值来进行数据的过滤

    学习猿地
  • SQL基本语法

    SQL 基本语法 表库操作 创建表 create table 表名( 字段名 类型(长度) 约束, 字段名 类型(长度)...

    李家酒馆酒保
  • MySQL表连接优化的初步分析

    每每一些很深刻的优化案例时,就会无比想念Oracle里的优化技巧,因为无论是从工具还是信息,都会丰富许多。

    jeanron100

扫码关注云+社区

领取腾讯云代金券