へっぽこブログ

【SQL】GROUP BY句 使い方を分かりやすく解説!

そもそもGROUP BY句とは

SQLでデータのグループ化を行うために使用するクエリです。
例として下記の図をご覧ください。

様々な商品の情報が入っているSYOHINテーブルがあるとします。
例えば、このテーブルから「商品分類」ごと(単位)に行数がどのくらいあるのか確認したい場合、
この量のデータなら目視で確認ができる量ですが、何百、何千とあった場合は目視は難しいです。
その際に「GROUP BY」と集約関数を使用することで簡単に確認することが可能になります。

GROUP BY句の使い方

基本構文

では、上記で出した例を使用してGROUP BY句の使い方を解説します。
まずGROUP BY句の基本構文は下記の通りです。

SELECT <列名1>, <列名2>, <列名3>,・・・
FROM <テーブル名>
GROUP BY <列名1>, <列名2>, <列名3>,・・・;

上記構文+WHEREを使用する際、GROUP BYの前で使用する必要があります。
実行順序はFROM → WHERE → GROUP BY → SELECTの順になります。

COUNT関数

指定した列名(カラム)の行数(レコード数)を取得する集約関数になります。
今回はこちらを使用して図の例でグループ化を行います。

SELECT category, COUNT(category)
FROM SYOHIN
GROUP BY catetory;

上記SQLを実行すると、、

+——————+—————————-+
|category…….| COUNT(category) |
+——————+—————————+
|衣類…………..|         2|
|事務用品……..|         2|
|食品…………..|         3|
+——————+—————————+

という結果になります。

COUNT関数を使用する際に注意したいことは、NULLの値についてです。

               NULLの扱いについて
COUNT(列名(カラム名))はNULLを数えずに行数(レコード数)を集計する
COUNT(*)はNULLを数えて行数(レコード数)を集計する


MAX関数とMIN関数

指定された列名(カラム)の最大値または、最小値を求める際に使用する集約関数になります。
使用方法は下記の通りになります。

●MAX関数

SELECT catetory, MAX(unit_price)
FROM SYOHIN
GROUP BY catetory;

上記SQLを実行すると、、

+——————+———————+
|category…….|MAX(unit_price)|
+——————+———————+
|衣類…………..|…...……..1200|
|事務用品……..|…………….420|
|食品…………..|…………….430|
+——————+———————+

という結果になります。
この場合は、category(商品分類)毎にunit_price(単価)の最大値を求めたSQLの結果になります。

●MIN関数

SELECT catetory, MIN(cost_price)
FROM SYOHIN
GROUP BY catetory;

上記SQLを実行すると、、

+——————+———————+
|category…….|MAX(cost_price)|
+——————+———————+
|衣類…………..|…………….320|
|事務用品……..|………………65|
|食品…………..|………………15|
+——————+———————+

という結果になります。
この場合は、category(商品分類)毎にcost_price(原価)の最小値を求めたSQLの結果になります。

MAX関数、MIN関数は原則的に順序がつけられるデータであれば最大値と最小値も決まる為、
どんなデータ型の列にも適用可能です。

SUM関数

指定された列(カラム)の合計を求める際に使用する集約関数です。
使用方法は下記の通りになります。

SELECT category, SUM(unit_price)
FROM SYOHIN
GROUP BY category;

上記SQLを実行すると、、

+——————+———————+
|category…….|SUM(unit_price)|
+——————+———————+
|衣類…………..|…...……..2060|
|事務用品……..|.....….....730|
|食品…………..|.....….....610|
+——————+———————+

という結果になります。

列(カラム)にNULLが入っている場合は計算前にNULLを除去してから計算を行います。

AVG関数

指定された列(カラム)の平均値を求める際に使用する集約関数です。
使用方法は下記の通りになります。

SELECT category, AVG(unit_price)
FROM SYOHIN
GROUP BY category;

上記SQLを実行すると、、

+——————+———————+
|category…….|AVG(unit_price)|
+——————+———————+
|衣類…………..|…...……..1030|
|事務用品……..|.....….....365|
|食品…………..|203.333333・・・|
+——————+———————+

という結果になります。

SUM関数と同様に列にNULLが入っている場合は、あらかじめ除去した形で計算が行われます。
その為、NULLと0は別の値であることに注意しましょう。

GROUP BYや集約関数にまつわる間違い

私自身が学んだ当初、実際によく間違ることがあった例をここでは紹介していきます。

SELECT句に集約キー以外の列名を使用してしまう

下記例を実行するとエラーが起きてしまいます。※

SELECT category, name, COUNT(unit_price)
FROM SYOHIN
GROUP BY category;

※MySQLだけはこの構文が認められている為、エラーにならずに実行可。

エラーが起きる理由としては、何らかのキーでグループ化を行ったのであれば結果に出てくる1行あたりの単位もそのグループになっている必要があります。
そのため、集約キーに対して複数の値が存在する列をSELECTで表示するには論理的には出来ないのです。

GROUP BYに別の列名を記述してしまう

「AS」というキーワードを使用することで、表示用の別名をつけることができます。
これをGROUP BY句で使用するとエラーが発生します。
※MySQLとPostgreSQLはこの構文が認められている為、エラーにならずに実行できますが、一般性ではない書き方になります。

SELECT category AS cg, COUNT(*)
FROM SYOHIN
GROUP BY category AS cg;

上記のSQL文がエラーになる理由は、DBMS内部でSQL文が実行される順序が関係してます。
SELECT句がGROUP BY句よりも後に実行される為、GROUP BY句の時点ではSELECT句で付けた別名を、DBMSはまだ知られていないからです。

では、どの順番でSQL文が処理されているのかは下記の「SQL実行順序」を参考にしてください。

SQL実行順序
FROM句(指定) → JOIN句(結合) → WHERE句(条件指定) → GROUP BY句(グループ化) →
SUM,MAX句(集約関数) → HAVING句(絞込み) → SELECT句(検索) → 
ORDER BY句(並替え) → LIMIT句(取得件数指定)

まとめ

いかがでしたでしょうか?
今回はGROUP BY句の基本的な使い方や注意したいことについて解説しました。
テーブルをグループ毎にまとめたい際は使用してみてください。
また、グループした結果条件指定したい場合別の記事に紹介します。

モバイルバージョンを終了