如果你编写 SQL 查询已有一段时间,那么你可能对 WHERE 子句非常熟悉。虽然它对聚合字段没有影响,但有一种方法可以根据聚合值过滤记录,那就是使用 HAVING 子句。本博客将介绍它的工作原理,并提供几个在 SELECT 查询中使用它的示例。


聚合和 Having 子句


聚合通常与分组结合使用。在 SQL 中,可以使用 GROUP BY 子句来实现。通过聚合和分组,我们可以深入了解数据。例如,一家电子商务公司可能希望跟踪特定时间段内的销售情况。


在很多情况下,我们可能不想在整个数据集上应用 GROUP BY 子句。在这种情况下,我们可以使用 GROUP BY 命令和有条件的 HAVING 子句来筛掉不需要的结果。与 WHERE 子句类似,HAVING 指定了一个或多个筛选条件,但针对的是一个组或一个聚合。因此,HAVING 总是放在 WHERE GROUP BY 子句之后,而在(可选的)ORDER BY 子句之前:



一些实例


为了更好地了解 HAVING 如何工作,让我们通过 Sakila 示例数据库 运行几个 SELECT 查询。


我们的第一个查询列出了租片次数最多的人,按降序排序,这样租片次数最多的人就排在最前面。我们将使用 HAVING 子句删除租片次数少于 3 次的客户,以在一定程度上缩短列表:



下面是 Navicat Premium 中的查询及其结果的第一页:



从这些租金数字来看,我们还可以再进一步缩小列表长度!


通过 WHERE HAVING 筛选行


正如 GROUP BY ORDER BY 应用于查询过程的不同阶段一样,WHERE HAVING 也是如此。因此,我们可以在分组和聚合之前和之后加入这两个子句来筛选结果。例如,我们可以添加一个 WHERE 子句,将结果限制在给定年份的上半年:



下面是在 Navicat Premium 中运行的上述查询及其结果的第一页:



组合多个条件


正如 WHERE 子句使用 AND OR 关键字支持多个条件一样,HAVING 子句也是如此。例如,我们可以将 HAVING 子句修改为类似下面的内容,从而找到租金数字在给定范围内的客户:


HAVING total_rentals >= 3 AND total_rentals <= 10