SQL 速習チュートリアル

SQL HAVING 句

1. SQL HAVING 句

HAVING 句は、集計関数(Aggregate Functions)に基づいた結果セットをフィルタリングするために使用されます。

個々の行をグループ化する「前」にフィルタリングを行う WHERE 句とは異なり、HAVING 句は集計が実行された「後」にグループに対してフィルタリングを行います。

1.1 HAVING の構文

SELECT カラム1, 集計関数(カラム2), カラム3, ...
FROM テーブル名
WHERE 条件 -- グループ化前のフィルタリング
GROUP BY カラム1, カラム3
HAVING 条件 -- グループ化および集計後のフィルタリング
ORDER BY カラム名;

2. デモ用データベース

以下は、Northwind サンプルデータベースの「Customers(顧客)」テーブルからの抜粋です。

CustomerID CustomerNameContactName Address CityPostalCode Country
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

3. SQL HAVING の使用例

次の SQL は、国ごとの顧客数を返しますが、顧客数が 5 人より多い国のみを抽出します。

実行例:

SELECT Country, COUNT(CustomerID) AS [顧客数]
FROM Customers
GROUP BY Country
HAVING COUNT(CustomerID) > 5;

次の SQL は、顧客数が 5 人より多い国を、件数の多い順(降順)にソートして返します。

実行例:

SELECT Country, COUNT(CustomerID) AS [顧客数]
FROM Customers
GROUP BY Country
HAVING COUNT(CustomerID) > 5
ORDER BY COUNT(CustomerID) DESC;

4. デモ用データベース(Orders & Employees)

以下は、Northwind サンプルデータベースの「Orders(注文)」テーブルからの抜粋です。

OrderID CustomerIDEmployeeIDOrderDateShipperID
102489051996-07-043
102498161996-07-051
102503441996-07-082

こちらは「Employees(従業員)」テーブルの抜粋です。

EmployeeIDLastNameFirstNameBirthDate PhotoNotes
1DavolioNancy1968-12-08EmpID1.pic教育背景には学士号が含まれます...
2FullerAndrew1952-02-19EmpID2.picAndrewはBTSを取得しました...
3LeverlingJanet1963-08-30EmpID3.picJanetは学士号を取得しています...

5. HAVING のさらなる応用例

次の SQL は、10 件を超える注文を登録した従業員を抽出します。

実行例:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS 注文数
FROM Orders
INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID
GROUP BY LastName
HAVING COUNT(Orders.OrderID) > 10;

次の SQL は、従業員「Davolio」または「Fuller」が、25 件を超える注文を登録したかどうかを返します。

実行例:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS 注文数
FROM Orders
INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID
WHERE LastName = 'Davolio' OR LastName = 'Fuller'
GROUP BY LastName
HAVING COUNT(Orders.OrderID) > 25;