SQLの複数の行をまとめるサンプルです。
集約関数とgroup by句とhaving句を使用します。
目次
| 複数行をまとめる | 集約関数 |
| 複数の行をグループごとにまとめる(group by) | |
| 集約関数の値に条件を指定する(having) | |
| グループごとの件数を表示する | |
| グループごとの件数を表示+group byで指定した項目にnullがある | |
| グループごとではなく、グループの件数を表示する | |
| 複数行を対象として最大値がある行を取得する |
集約関数
集約関数は、複数の行をまとめて1つの列の平均や合計などの計算結果を返します。
| 集約関数 | 説明 |
|---|---|
| SUM() | 合計を返す |
| AVG() | 平均を返す |
| MAX() | 最大値を返す |
| MIN() | 最小値を返す |
| COUNT() | 個数を返す |
集約関数の使用例
次のテーブルがあるとします。
| id | name | price |
|---|---|---|
| 1 | りんご | 300 |
| 2 | みかん | 200 |
| 3 | 白菜 | 200 |
| 4 | 玉ねぎ | 100 |
SQL
上記テーブルに対して集約関数を使用してデータを抽出します。
SELECT SUM(price),AVG(price),MAX(price),MIN(price),COUNT(price)
FROM sales;
1行目は、それぞれ集約関数を使用しています。
結果
結果は、以下のとおりです。
| SUM(price) | AVG(price) | MAX(price) | MIN(price) | COUNT(price) |
|---|---|---|---|---|
| 800 | 200 | 300 | 100 | 4 |
複数の行が1行になり集約関数の値が表示されます。
複数の行をグループごとにまとめる(group by)
| select 項目 from テーブル名 group by 項目 [,項目] |
- group byで指定した項目で、複数の行をまとめます。
- select句で指定する項目(※1)は、gourp byの項目として指定している必要があります。
→group byに項目があり、select句の後に項目がない場合は実行できます。
※1 集約関数と定数は除きます。
group byの使用例
次のテーブルがあるとします。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 野菜 | 白菜 | 200 |
| 2 | 野菜 | 玉ねぎ | 100 |
SQL
上記テーブルに対してgroup by句を使用してデータを抽出します。
SELECT category,AVG(price)
FROM sales
group by category;
3行目は、group by句を指定しています。
結果
結果は、以下のとおりです。
| category | AVG(price) |
|---|---|
| フルーツ | 250 |
| 野菜 | 150 |
group by句で指定した項目「category」の値でまとめられた行が表示されます。
また、その行ごとに集約関数の値が表示されます。
group byの項目を複数にした場合
group byに項目のshopを追加した場合は、
SELECT shop,category,AVG(price)
FROM sales
group by shop,category
order by shop,category;
shop,categoryの単位で行がまとまります。
| shop | category | AVG(price) |
|---|---|---|
| 1 | フルーツ | 250 |
| 1 | 野菜 | 200 |
| 2 | 野菜 | 100 |
集約関数の値に条件を指定する(having)
| select 項目 from テーブル名 group by 項目 having 条件 |
- having句を使用すると、複数の行をグループごとにまとめた列の集約関数の値に条件を指定できます。
havingの使用例
次のテーブルがあるとします。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 野菜 | 白菜 | 200 |
| 2 | 野菜 | 玉ねぎ | 100 |
SQL
上記テーブルに対してhaving句を使用してデータを抽出します。
SELECT category,AVG(price)
FROM sales
group by category
having AVG(price) > 200;
4行目は、having句を指定しています。
処理のイメージ
処理のイメージは、以下のとおりです。
1.group by句で指定した項目「category」の単位でまとめらます。
| category | AVG(price) |
|---|---|
| フルーツ | 250 |
| 野菜 | 150 |
2.AVG(price)の列に対してhaving句で指定した条件(200より大きい)を満たす行が表示されます。
| category | AVG(price) |
|---|---|
| フルーツ | 250 |
where句を使用した場合
以下のように、where句で、集約関数(AVG)の結果を条件にすることはできません。
SELECT category,AVG(price)
FROM sales
where AVG(price) > 200
group by category;
MySQLでは、以下のメッセージが表示されます。
#1111 - 集計関数の使用方法が不正です。
集約関数の結果を条件にする場合は、having句を使用します。
where句を使用できるパターン
ただし、集約関数の結果以外を条件にする場合は、group byとwhereを使用できます。
SELECT category,AVG(price)
FROM sales
where name = 'りんご'
group by category;
この場合は、件数を絞れるwhereを使用した方が良いです。having句は処理が遅くなります。
グループごとの件数を表示するサンプル
グループごとの件数を表示するサンプルです。よく使われます。
次のテーブルがあるとします。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 野菜 | 白菜 | 200 |
| 2 | 野菜 | 玉ねぎ | 100 |
SQL
上記テーブルに対してカテゴリ(category)ごとの件数を求めます。
select category,count(category) as cnt
from sales
group by category;
1行目は、countでcategoryの件数を求めています。
3行目は、group byでcategory単位でまとめています。
結果
結果は、以下のとおりです。
| category | cnt |
|---|---|
| フルーツ | 2 |
| 野菜 | 2 |
カテゴリごとに、何件あるのかがわかります。
グループごとの件数を表示+group byで指定した項目にnullがある
グループごとの件数を表示+group byで指定した項目にnullがあるサンプルです。
次のテーブルがあるとします。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 白菜 | 200 | |
| 2 | 玉ねぎ | 100 |
SQL
上記テーブルに対してカテゴリ(category)ごとの件数を求めます。
select category,count(category) as cnt
from sales
group by category;
1行目は、countでcategoryの件数を求めています。
結果
結果は、以下のとおりです。
| category | cnt |
|---|---|
| 0 | |
| 野菜 | 2 |
カテゴリはnullで、件数は0件で表示されます。
ヒット件数が0件のとき
以下のように条件を指定してヒット件数が0件のときは、
select category,count(category) as cnt
from sales
where shop> 10
group by category;
以下のようにデータ自体ありません。
| category | cnt |
|---|---|
グループごとではなく、グループの件数を表示する
グループごとではなく、グループの件数を表示するサンプルです。
次のテーブルがあるとします。
カテゴリの野菜、フルーツの2種類の2を抽出したい場合です。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 野菜 | 白菜 | 200 |
| 2 | 野菜 | 玉ねぎ | 100 |
SQL
上記テーブルに対してグループの件数を求めます。
select count(distinct category) as cnt from sales;
distinctでcategoryの重複行をまとめ、countでその件数を求めています。
結果
結果は、以下のとおりです。
| cnt |
|---|
| 2 |
カテゴリの件数がわかります。
nullの場合
categoryの値が全てnullのときに、上記のSQLを実行した場合は0が表示されます。
nullの行もカウントしたい
nullの行も1行としたいときは、nullをNVLで置き換えます(oracle)。
次のテーブルがあるとします。
| shop | category | name | price |
|---|---|---|---|
| 1 | フルーツ | りんご | 300 |
| 1 | フルーツ | みかん | 200 |
| 1 | 白菜 | 200 | |
| 2 | 玉ねぎ | 100 |
SQL
上記テーブルに対してグループの件数を求めます。
select count(distinct NVL(category,'test')) as cnt from sales;
結果
結果は、以下のとおりです。
| cnt |
|---|
| 2 |
nullも1行としてカウントされます。
複数行を対象として最大値がある行を取得する
次のテーブルがあるとします。
idの単位でのrow_noが最大値の行を取得します。
Testテーブル
| id | row_no | memo |
|---|---|---|
| 1001 | 1 | |
| 1001 | 2 | |
| 1002 | 1 | |
| 1002 | 2 | |
| 1002 | 3 |
SQL
上記テーブルに対してgroup by句とmaxを使用してデータを抽出します。
select id,max(row_no) as row_no from Test
group by id
結果
結果は、以下のとおりです。
| id | row_no |
|---|---|
| 1001 | 2 |
| 1002 | 3 |
関連の記事
SQL distinct 重複行を表示しないサンプル
SQL LEFT JOIN 外部結合のサンプル
SQL 副問合せのサンプル(サブクエリ)
