MySQL の GROUP BY と HAVING

ここでは MySQL の GROUP BY と HAVING についてご説明します。

サンプルデータベースのテーブルを使いますので、実際にスクリプトを実行してみたい方は、こちら のスクリプトを実行して school_db データベースを作成しておいてください。

GROUP BY でグルーピングして集計する

MySQLの SELECT 文で GROUP BY を使うと、行をグループ化して、そのグループごとに集計したりすることができます。

よく使う基本の SELECT 文の構文は次の通りで、GROUP BY は以下の位置に追加します。

SELECT select_expr
[ FROM table_references ] 
[ WHERE where_condition ] 
[ GROUP BY {col_name | expr | position} ] 
[ HAVING where_condition ] 
[ ORDER BY {col_name | expr | position} [ ASC | DESC ] ]
[ LIMIT {[offset,] row_count | row_count OFFSET offset} ];

実際に例をあげて GROUP BY を使いながら、使い方をご説明します。

次のような exam_results テーブルがあります。

MySQL の GROUP BY と HAVING 1


この exam_results テーブルから exam_id ごとの最大値 (MAX) 、最小値 (MIN) を取得するには、GROUP BY を使って次のようにできます。

SELECT      exam_id,
            MIN(score) AS min_score,
            MAX(score) AS max_score
FROM        exam_results
GROUP BY    exam_id;

[実行結果]

MySQL の GROUP BY と HAVING 2

exam_id = 1 と 2 の最高点と最低点が取得できていますね。


GROUP BY を使うと SELECT 句に指定できるカラムは GROUP BY で指定したカラムと、集計関数や定数など、グループごとにひとつの値を返すものだけになります。

それ以外のカラムを SELECT 句で指定すると、以下のようにエラーになります。

MySQL の GROUP BY と HAVING 3


GROUP BY で複数のカラムを指定してグルーピンクする

GROUP BY の後にはカラム名だけでなく、エイリアス名や、関数や計算された値など指定することができます。

SELECT 句のカラムのインデックスも指定できますが、わかりにくくなるので、あまりおすすめしません。

また GROUP BY で複数のカラムを指定してグルーピンクすることも可能です。


次のような students テーブルがあります。

MySQL の GROUP BY と HAVING 4


この students テーブルから誕生日の年ごと、性別ごとでグルーピングした学生の人数を知りたい場合、次のように取得することができます。

GROUP BY の後にまずは birth_year というエイリアス名を指定して誕生年でグルーピングし、次に gender でグルーピングしています。

COUNT(*) で、グループごとのレコードの数を取得できます。

SELECT      YEAR(birthday) AS birth_year,
            gender,
            COUNT(*) AS student_count
FROM        students
GROUP BY    birth_year,
            gender;

[実行結果]

MySQL の GROUP BY と HAVING 5

birth_year と gender でグループ化されて、それぞれのグループの学生の数が取得できていますね。

エイリアスを使わず、GROUP BY YEAR(birthday), gender; としても同じ結果になります。


HAVING でグループの条件を指定する

GROUP BY 句と一緒に使われて、結果セットに含めるグループの条件を指定できるのが、HAVING 句です。


先ほど、students テーブルから誕生日の年ごと、性別ごとでグルーピングした学生の人数を取得しました。

その時に学生の数が二人以上存在するグループのみを取得したいような時は、HAVING を使って次のように指定することができます。

SELECT      YEAR(birthday) AS birth_year,
            gender,
            COUNT(*) AS student_count
FROM        students
GROUP BY    birth_year,
            gender
HAVING		student_count > 1;

[実行結果]

MySQL の GROUP BY と HAVING 6

学生の数が二人以上存在するグループのみが取得できていますね。

こちらもエイリアスを使わず、HAVING COUNT(*) > 1 としても同じ結果になります。


以上、MySQL の GROUP BY と HAVING についてご説明しました。

© 2024 MySQL 入門