SQL 中 HAVING 和 WHERE 的区别

Difference between HAVING and WHERE in SQL

我看过in other questionsSQL中HAVINGWHERE的区别是用了HAVINGpost-聚合而 WHERE 用于预聚合。但是,我仍然不确定何时使用预聚合过滤或 post-聚合过滤。

举个具体的例子,为什么这两个查询不会产生相同的结果(第二个查询以压缩 GROUP BY 调用的方式过早地求和 quantity)?

使用WHERE获取每个房地产经纪人的公寓销售数量。

SELECT agentId, SUM(quantity) total_sales 
  FROM sales s, houses h
  WHERE s.houseId = h.houseId AND h.type = "condo"
  GROUP BY agentId
  ORDER BY total_sales;

尝试使用 HAVING 获得与上述相同的数量。

SELECT agentId, SUM(quantity) total_sales 
  FROM sales s, houses h
  GROUP BY agentId
  HAVING s.houseId = h.houseId AND h.type = "condo"
  ORDER BY total_sales;

注意:这些是 sqlite3 中的 written/tested/executed。

首先,学习使用正确、明确的标准JOIN语法。

其次,您的查询应如下所示:

SELECT s.agentId, SUM(s.quantity) as total_sales 
FROM sales s JOIN
     houses h
     ON s.houseId = h.houseId
WHERE h.type = 'condo'
GROUP BY s.agentId
ORDER BY total_sales;

您的查询版本应该会在任何合理的数据库中生成错误,因为 HAVING 子句包含既不是 GROUP BY 键也不是聚合函数的列。

补充说明:

  • 字符串的分隔符是单引号。如果您使用双引号,事情可能不会像您预期的那样工作。
  • 您应该限定所有列引用,尤其是当您的查询引用多个列时 table。
  • JOIN 条件属于 ON 子句,而不属于 WHERE 子句。
  • h.type 聚合之后进行过滤没有任何意义。如果确实有效,sum() 将包括非公寓,因为过滤发生得太晚了。

WHERE 从数据库中过滤行。然后,如果查询有聚合,聚合是运行基于聚合函数和查询中的GROUP BY子句。在那之后,应用 HAVING 来过滤分组结果。 HAVING 允许的唯一过滤是对 GROUP BY 列或计算的聚合进行过滤。

我必须假设您正在使用 MySQL 作为示例查询,因为正如其他答案所指出的那样,您的 HAVING 子句没有意义并且 MySQL 有一些偶尔会出现问题和令人困惑的默认行为。

考虑它的简单方法是考虑应用步骤的顺序。

第 1 步:Where 子句过滤数据

第 2 步:实施分组依据 (SUM / MAX / MIN / ETC)

第 3 步:Having 子句过滤结果

因此在您的 2 个示例中:

SELECT agentId, SUM(quantity) total_sales 
FROM sales s, houses h
WHERE s.houseId = h.houseId AND h.type = "condo"
GROUP BY agentId
ORDER BY total_sales;

第 1 步:按 HouseId 和 Condo 过滤

第 2 步:将结果相加 (与 houseid 和 condo 匹配的房屋数量)

SELECT agentId, SUM(quantity) total_sales 
FROM sales s, houses h
GROUP BY agentId
HAVING s.houseId = h.houseId AND h.type = "condo"
ORDER BY total_sales;

第 1 步:无过滤器

第 2 步:将所有房屋的数量相加

第 3 步:按 houseid 和 condo 过滤结果。

希望这能澄清正在发生的事情。

决定使用哪种方式的最简单方法是: - 使用 WHERE 过滤数据 - 使用 HAVING 过滤聚合结果 (SUM / MAX / MIN / ETC)