SQL Server - GROUP BY
概要
複数の行を各グループに集約する (GROUP BY)
下表に示すテーブルがある。
| Shop_ID | Category | Name | Price |
|---|---|---|---|
| 1 | Fruit | Apple | 300 |
| 1 | Fruit | Orange | 200 |
| 1 | Vegetable | Carrot | 200 |
| 2 | Vegetable | Eggplant | 100 |
以下に、GROUP BY句のシンタックスを示す。
GROUP BY句で指定したカラム名で、複数の行を集約する。
SELECT句のカラム名とGROUP BY句のカラム名は一致している必要はない。
SELECT <カラム名> FROM <テーブル名>
GROUP BY <カラム名>
以下の例では、上記のT_Salesテーブルに対して、GROUP BY句を使用してデータを抽出している。
SELECT Category, AVG(Price)
FROM T_Sales
GROUP BY Category;
結果は、以下の通りである。
GROUP BY句で指定したCategoryカラムの値で集約されたレコードが表示される。
また、各レコードごとに集約関数の値が表示される。
Category AVG(Price) Fruit 250 Vegetable 150
以下の例では、GROUP BY句にShop_IDカラムとCategoryカラムを追加する時、Shop_IDカラムとCategoryカラムでレコードが集約されている。
SELECT Shop_ID, Category, AVG(Price)
FROM T_Sales
GROUP BY Shop_ID, Category
ORDER BY Shop_ID, Category;
Shop_ID Category AVG(Price) 1 Fruit 250 1 Vegetable 200 2 Vegetable 100
集約関数の値に条件を指定する (HAVING句)
HAVING句の使用
下表に示すテーブルがある。
| Shop_ID | Category | Name | Price |
|---|---|---|---|
| 1 | Fruit | Apple | 300 |
| 1 | Fruit | Orange | 200 |
| 1 | Vegetable | Carrot | 200 |
| 2 | Vegetable | Eggplant | 100 |
以下に、HAVING句のシンタックスを示す。
HAVING句を使用すると、複数のレコードを各グループに集約して、集約関数の値に条件を指定できる。
SELECT <カラム名>
FROM <テーブル名>
GROUP BY <カラム名>
HAVING <条件>
以下の例では、上記のT_Salesテーブルに対して、HAVING句を使用してデータを抽出している。
SELECT Category, AVG(Price)
FROM T_sales
GROUP BY Category
HAVING AVG(Price) > 200;
以下に、上記のSQL文の処理のイメージを示す。
1. まず、GROUP BY句で指定したCategoryカラムの単位で集約する。
| Category | AVG(Price) |
|---|---|
| Fruit | 250 |
| Vegetable | 150 |
2. 次に、AVG(Price)のカラムに対して、HAVING句で指定した条件(200より大きい)を満たすレコードが表示される。
| Category | AVG(Price) |
|---|---|
| Fruit | 250 |
WHERE句が使用できない場合
以下のように、WHERE句で、集約関数(AVG)の結果を条件にすることはできない。
MySQLでは、以下のメッセージが表示される。
#1111 - 集計関数の使用方法が不正です。
集約関数の結果を条件にする場合は、HAVING句を使用する。
SELECT Category, AVG(Price)
FROM T_Sales
WHERE AVG(Price) > 200
GROUP BY Category;
WHERE句が使用できるパターン
ただし、集約関数の結果以外を条件にする場合は、GROUP BY句とWHERE句が使用できる。
この場合、レコード件数を絞るWHERE句を使用した方がよい。
HAVING句では処理が遅くなる可能性がある。
SELECT Category, AVG(Price)
FROM T_Sales
WHERE Name = 'Apple'
GROUP BY Category;