SQL 中 HAVING 和 WHERE 的区别
Difference between HAVING and WHERE in SQL
我看过in other questionsSQL中HAVING
和WHERE
的区别是用了HAVING
post-聚合而 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)
我看过in other questionsSQL中HAVING
和WHERE
的区别是用了HAVING
post-聚合而 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)