我已经看到in other questions,在SQL中HAVING
和WHERE
之间的区别是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中编写/测试/执行的。
答案 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()
将包括非公寓,因为过滤发生得太晚了。