目录
在本文中学习何时使用WHERE和HAVING。两者都执行类似的功能,但用于不同的目的!
本文的所有示例都基于Microsoft SQL Server Management Studio和AdventureWorks2012数据库。
Where和Having有何不同?
使用更高级的SQL时,可能不清楚何时使用WHERE与HAVING子句才是有意义的。
虽然看起来两个子句都做同样的事情,但它们以不同的方式做到的。事实上,它们的功能相互补充。
- 使用WHERE子句是结果中的过滤器记录。过滤器在进行任何分组之前进行。
- HAVING子句用于过滤组中的值。
在我们继续之前,让我们回顾一下SQL语句的格式。它是
SELECT
FROM
WHERE
GROUP BY
HAVING
为了帮助保持正确,我喜欢从上到下考虑SQL语句的执行顺序。这意味着首先将WHERE子句应用于结果,然后根据GROUP BY汇总剩余的行。
WHERE子句
WHERE子句用于从结果中过滤行。例如
SELECT COUNT(SalesOrderID)
FROM Sales.SalesOrderDetail
返回121,317作为计数,而查询
SELECT COUNT(SalesOrderID)
FROM Sales.SalesOrderDetail
WHERE UnitPrice > 200
返回48,159作为计数。这是因为WHERE子句从结果中过滤出UnitPrice小于或等于200的73,158个SalesOrderDetails。
HAVING子句
HAVING子句用于过滤GROUP BY中的值。您可以使用它们来过滤掉分组,如下
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING SalesOrderID > 50000
但它们的真正力量在于它们能够根据聚合函数结果进行比较和过滤。例如,您可以选择总额超过10,000美元的所有订单
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING SUM(UnitPrice * OrderQty) > 10000
由于WHERE子句的可见性是一次一行,因此无法在所有SalesOrderID中评估SUM。在创建分组后评估HAVING子句。
结合两者:WHERE和HAVING
当SQL语句同时具有WHERE子句和HAVING子句时,请记住首先应用WHERE子句,然后将结果分组,最后根据HAVING子句过滤组。
在许多情况下,您可以将WHERE条件放在HAVING子句中,例如
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING SUM(UnitPrice * OrderQty) > 10000
AND SalesOrderID > 50000
Vs
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
WHERE SalesOrderID > 50000
GROUP BY SalesOrderID
HAVING SUM(UnitPrice * OrderQty) > 10000
如果你可以从having子句中的where子句中添加条件那么为什么甚至担心WHERE?我可以使用此查询吗?
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING SUM(UnitPrice * OrderQty) > 10000 AND LineTotal > 10
实际上该查询会生成错误。LineTotal列不是按字段列表的组成部分,也不是总计的结果。
为了有效,having子句只能比较聚合函数的结果或组的列部分。
为了有效,必须将查询重写为
SELECT SalesOrderID,
SUM(UnitPrice * OrderQty) AS TotalPrice
FROM Sales.SalesOrderDetail
WHERE LineTotal > 100
GROUP BY SalesOrderID
HAVING SUM(UnitPrice * OrderQty) > 10000
总结一下WHERE和HAVING的区别:
- WHERE用于在任何分组发生之前过滤记录。
- HAVING用于在组成为组后过滤值。只有组中的列或表达式才能包含在HAVING子句的条件中。