HAVING 句を使用した行の選択

WHERE が SELECT とやり取りするように、HAVING 句は GROUP BY 句に対して条件を設定します。WHERE 検索条件がグループ化操作の前に適用されるのに対し、HAVING 検索条件はグループ化操作の発生後に適用されます。HAVING 構文は、集計関数を含めることができる点を除けば、WHERE 構文と同じです。HAVING 句では、選択リスト内の項目はどれでも参照できます。

次の例では、SalesOrderDetail テーブルを製品 ID でグループ化し、注文の合計金額が $1,000,000 を超えていて、平均注文数が 3 個未満の製品のグループのみを含めます。

USE AdventureWorks2008R2;
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 AdventureWorks2008R2;
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)

製品ごとの計算対象が少なくとも 1,500 アイテムを超えるようにする場合は、HAVING COUNT(*) > 1500 を使用して、1,500 未満の販売数に対する販売金額を返す製品を除外します。クエリは次のようになります。

USE AdventureWorks2008R2;
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 クエリ オプティマイザーは、これらの条件のほとんどを処理できます。HAVING 検索条件をグループ化操作の前に適用できると判断すると、そのように処理します。ただし、グループ化操作の前に適用できるすべての HAVING 検索条件をクエリ オプティマイザーが認識できるとは限りません。そのような検索条件はすべて、HAVING 句ではなく WHERE 句に記述することをお勧めします。

この例では、HAVING 句を集計関数と共に使用します。SalesOrderDetail テーブルの行を製品 ID でグループ化し、平均注文数が 5 個以下の製品を除外します。

USE AdventureWorks2008R2;
GO
SELECT ProductID 
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING AVG(OrderQty) > 5
ORDER BY ProductID ;
GO

次の例では、HAVING 句を集計関数なしで使用します。ProductModel テーブルの行を名前でグループ化し、"Mountain" から始まっていない名前を除外します。

USE AdventureWorks2008R2;
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 句の出力を順序付けることができます。

関連項目

参照