SQL中的HAVING和WHERE之间的区别

时间:2018-11-27 22:33:50

标签: sql sqlite aggregation having

我已经看到in other questions,在SQL中HAVINGWHERE之间的区别是HAVING是在聚合,而WHERE用于预聚合。但是,我仍然不确定何时使用聚合前过滤或聚合后过滤。

作为一个具体示例,为什么这两个查询没有产生相同的结果(第二个和quantity过早地压缩了GROUP BY调用)?

使用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中编写/测试/执行的。

3 个答案:

答案 0 :(得分:1)

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

我必须假设您在示例查询中使用MySQL,因为正如其他答案所指出的那样,您的HAVING子句没有意义,并且MySQL具有一些默认行为,有时会出现问题和混乱。 / p>

答案 1 :(得分:1)

一种简单的思考方法是考虑步骤的应用顺序。

第1步:where子句过滤数据

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

第3步:让子句过滤结果

在您的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步:将结果相加    (与房屋和公寓匹配的房屋数量)

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步:按房屋和公寓过滤结果。

希望这可以清除正在发生的事情。

决定应该使用哪个的最简单方法是:  -使用WHERE过滤数据  -使用HAVING过滤汇总结果(SUM / MAX / MIN / ETC)

答案 2 :(得分:0)

首先,学习使用正确的,明确的,标准 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键也不是聚合函数。

其他说明:

  • 字符串的定界符是单引号。如果使用双引号,则可能无法按预期运行。
  • 您应限定所有列引用,尤其是当查询引用多个表时。
  • JOIN条件属于ON子句,而不属于WHERE子句。
  • h.type之后的 上进行过滤没有任何意义。如果确实有效,则sum()将包括非公寓,因为过滤发生得太晚了。