HAVING 子句對 GROUP BY 子句設置條件的方式與 WHERE 和 SELECT 的交互方式類似。WHERE 搜索條件在進行分組操作之前應用;而 HAVING 搜索條件在進行分組操作之后應用。HAVING 語法與 WHERE 語法類似,但 HAVING 可以包含聚合函數。HAVING 子句可以引用選擇列表中顯示的任意項。
下面的示例按產品 ID 對 SalesOrderDetail 進行了分組,並且只包含那些訂單合計大於 $1,000,000 且其平均訂單數量小於 3 的產品組。
USE AdventureWorks;
GO
SELECT ProductID, AVG(OrderQty) AS AverageQuantity, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING SUM(LineTotal) > $1000000.00
AND AVG(OrderQty) < 3 ;
GO
請注意,如果 HAVING 中包含多個條件,那么這些條件將通過 AND、OR 或 NOT 組合在一起。
若要查看總銷量大於 $2,000,000 的產品,請使用下面的查詢:
USE AdventureWorks;
GO
SELECT ProductID, Total = SUM(LineTotal)
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING SUM(LineTotal) > $2000000.00 ;
GO
下面是結果集:
ProductID Total
----------- ----------------------
781 3864606.54937208
969 2010943.97244001
793 2897478.01200001
784 3699803.72383008
780 3880441.60780208
976 2079038.42948
795 2268057.09000002
783 4548164.01783709
779 4170215.3849281
782 5032968.13026809
794 2679200.01336002
753 2006264.4236
(12 row(s) affected)
若要確保對每種產品的計算中至少包含 1500 項,請使用 HAVING COUNT(*) > 1500 消除返回的銷售總數小於 1500 項的產品。該查詢類似於下面的示例:
USE AdventureWorks;
GO
SELECT ProductID, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING COUNT(*) > 1500 ;
GO
理解應用 WHERE、GROUP BY 和 HAVING 子句的正確順序對編寫高效的查詢代碼會有所幫助:
WHERE 子句用來篩選 FROM 子句中指定的操作所產生的行。
GROUP BY 子句用來分組 WHERE 子句的輸出。
HAVING 子句用來從分組的結果中篩選行。
對於可以在分組操作之前或之后應用的任何搜索條件,在 WHERE 子句中指定它們會更有效。這樣可以減少必須分組的行數。應當在 HAVING 子句中指定的搜索條件只是那些必須在執行分組操作之后應用的搜索條件。
Microsoft SQL Server 2005 查詢優化器可以處理這些條件中的大多數條件。如果查詢優化器確定 HAVING 搜索條件可以在分組操作之前應用,那么它就會在分組之前應用。查詢優化器可能無法識別所有可以在分組操作之前應用的 HAVING 搜索條件。建議將所有這些搜索條件放在 WHERE 子句中,而不是 HAVING 子句中。
下面的示例顯示了帶有聚合函數的 HAVING 子句。它按產品 ID 分組 SalesOrderDetail 表中的行,並消除其平均訂單數量小於/等於 5 的產品。
USE AdventureWorks;
GO
SELECT ProductID
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING AVG(OrderQty) > 5
ORDER BY ProductID ;
GO
下面的示例顯示了不帶聚合函數的 HAVING 子句。它按名稱分組 ProductModel 表中的行,並消除那些不以 Mountain 開頭的名稱。
USE AdventureWorks;
GO
SELECT pm.Name, AVG(ListPrice) AS 'Average List Price'
FROM Production.Product AS p
JOIN Production.ProductModel AS pm
ON p.ProductModelID = pm.ProductModelID
GROUP BY pm.Name
HAVING pm.Name LIKE 'Mountain%'
ORDER BY pm.Name ;
GO
請注意,ORDER BY 子句可用於排序 GROUP BY 子句的輸出。