【重学 MySQL】三十九、Having 的使用
- 基本语法
- 示例
- 示例 1:使用 `HAVING` 过滤分组
- 示例 2:`HAVING` 与 `WHERE` 的结合使用
- 注意点
- `WHERE` 与 `HAVING` 的对比
- 基本定义与用途
- 主要区别
- 示例对比
- 总结
在 MySQL 中,HAVING
子句主要用于对 GROUP BY
语句产生的分组结果进行条件过滤。虽然 WHERE
子句也用于设置条件以过滤记录,但 WHERE
无法直接对聚合函数(如 COUNT()
, MAX()
, MIN()
, SUM()
, AVG()
等)的结果进行过滤。这正是 HAVING
子句的用武之地。
基本语法
SELECT column_name(s), AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);
示例
假设我们有一个名为 orders
的表,包含字段 order_id
, customer_id
, order_date
, 和 amount
。
示例 1:使用 HAVING
过滤分组
如果我们想要找出订单总额超过 1000 的客户,我们可以使用 GROUP BY
和 HAVING
来实现:
SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > 1000;
这个查询会返回所有订单总额超过 1000 的 customer_id
以及他们对应的订单总额。
示例 2:HAVING
与 WHERE
的结合使用
虽然 HAVING
主要用于对聚合函数的结果进行过滤,但它也可以与 WHERE
子句一起使用,其中 WHERE
子句用于在分组前过滤记录,而 HAVING
子句用于在分组后过滤结果。
SELECT customer_id, SUM(amount) AS total_amount
FROM orders
WHERE order_date > '2023-01-01' -- 过滤 2023 年 1 月 1 日之后的订单
GROUP BY customer_id
HAVING SUM(amount) > 1000; -- 过滤订单总额超过 1000 的客户
这个查询会首先筛选出 2023 年 1 月 1 日之后的订单,然后按 customer_id
进行分组,并计算每个客户的订单总额,最后只返回订单总额超过 1000 的客户及其订单总额。
注意点
HAVING
子句在GROUP BY
子句之后执行,因此对分组后的结果进行过滤。HAVING
可以使用聚合函数,而WHERE
子句则不能。- 在实际应用中,如果条件可以在数据分组前通过
WHERE
子句进行过滤,则应优先使用WHERE
,因为WHERE
过滤的数据更少,有助于提高查询效率。 HAVING
子句也支持使用别名(如上例中的total_amount
),但只能在HAVING
子句中引用,不能在WHERE
子句中引用。- 当过滤条件中有聚合函数时,则此过滤条件必须声明在
HAVING
中,当过滤条件中没有聚合函数时,则此过滤条件声明在WHERE
或HAVING
中都可以,但是,建议大家声明在WHERE
中
WHERE
与 HAVING
的对比
在SQL中,WHERE
和HAVING
是两个用于过滤数据的关键字,它们虽然功能相似,但在使用场景和效果上存在显著差异。
基本定义与用途
-
WHERE:
WHERE
子句是SQL查询中用于筛选结果集的可选部分。- 它使用布尔表达式来限制返回的行数,筛选数据并检索特定信息。
WHERE
子句在数据分组(如果有的话)之前进行过滤,基于表中的列数据来限制返回的数据行。
-
HAVING:
HAVING
子句是一个与GROUP BY
子句配合使用的条件语句,用于在数据分组后对分组结果进行过滤。- 它基于分组后的聚合结果进行筛选,可以使用聚合函数(如SUM、AVG、COUNT等)和逻辑操作符。
主要区别
-
使用时机:
WHERE
子句在数据分组之前进行过滤,而HAVING
子句在数据分组之后进行过滤。- 如果没有使用
GROUP BY
子句,则HAVING
的行为与WHERE
类似,但HAVING
支持聚合函数的使用,而WHERE
不支持。
-
支持的函数:
WHERE
子句不能使用聚合函数作为过滤条件。HAVING
子句可以使用聚合函数作为过滤条件,因为它是在分组后对聚合结果进行筛选。
-
字段别名:
- 在
WHERE
子句中,通常不能直接使用字段别名(在某些数据库系统中可能支持,但这不是标准行为)。 - 在
HAVING
子句中,可以使用字段别名(尤其是当别名是基于聚合函数的结果时)。
- 在
-
执行顺序:
- 在SQL查询的执行顺序中,
WHERE
子句早于GROUP BY
子句执行,而HAVING
子句则在GROUP BY
之后执行。
- 在SQL查询的执行顺序中,
示例对比
假设有一个名为orders
的表,包含order_id
、customer_id
和sales_amount
等字段,我们想要找出销售额大于1000美元的客户。
-
使用
WHERE
(假设不分组,仅筛选):SELECT customer_id, sales_amount FROM orders WHERE sales_amount > 1000;
这个查询将返回所有销售额大于1000美元的单条订单记录。
-
使用
HAVING
(假设按客户分组):SELECT customer_id, SUM(sales_amount) AS total_sales FROM orders GROUP BY customer_id HAVING total_sales > 1000;
这个查询将首先按
customer_id
分组订单,然后计算每个客户的总销售额,并返回总销售额大于1000美元的客户组。
总结
WHERE
和HAVING
在SQL查询中各自扮演着重要的角色,它们的主要区别在于使用时机、支持的函数、字段别名的使用以及执行顺序。了解这些区别对于编写有效的SQL查询至关重要。