データをグループ化して合計や平均を計算(GROUP BY句, HAVING句)

データの個数を調べる関数やカラム毎の値を集計する関数などを使用する時に、全てのデータをまとめて対象とするのではなく特定のカラムを値を使ってグループ化を行いグループ単位で集計などを行うことができます。ここでは SQLite でグループ化を行う時に使用する GROUP BY 句の使い方、及びグループ化した後で絞り込みを行うために使用する HAVING 句について解説します。

(Last modified: )

GROUP BY句を使ったグループ化

最初に GROUP BY 句を使ったグループ化の方法です。書式は次の通りです。

SELECT カラム名, ... FROM テーブル名
  GROUP BY カラム名1, カラム名2, ...;

GROUP BY 句の後に指定したカラム名の値が同じものが同じグループとなります。複数のカラムを指定した場合は、値の組み合わせが同じものでグループ化されます。

少し分かりにくいかもしれないので実際の例を見て下さい。

例として次のようなテーブルを作成しました。

create table user(name text, gender text, address text);

GROUP BY句を使ったグループ化(1)

INSERT 文を使ってテーブルにデータをいくつか格納しておきます。

insert into user values('Honda', 'man', 'Tokyo');
insert into user values('Ooshima', 'woman', 'Osaka');
insert into user values('Shima', 'woman', 'Tokyo');
insert into user values('Yamada', 'man', 'Nagoya');
insert into user values('Fukushi', 'man', 'Fukuoka');
insert into user values('Eda', 'woman', 'Osaka');
insert into user values('Kiuchi', 'man', 'Tokyo');

GROUP BY句を使ったグループ化(2)

このテーブルからそのままデータを取得した場合には次のようになります。

select * from user;

GROUP BY句を使ったグループ化(3)

まず count 関数を使ってテーブル全体のデータの行数を取得してみます。( count 関数については「count関数」を参照して下さい)。

select count(*) from user;

GROUP BY句を使ったグループ化(4)

次に GROUP BY 句を使い gender カラムでグループ化を行い、グループ毎に含まれるデータの行数を取得します。

select gender, count(*) from user group by gender;

GROUP BY句を使ったグループ化(5)

gender カラムに含まれる値毎にデータの行数が取得できました。同じように今度は address カラムでグループ化を行いデータの行数を取得します。

select address, count(*) from user group by address;

GROUP BY句を使ったグループ化(6)

address カラムに含まれる値毎にデータの行数が取得できました。最後に複数のカラムでグループ化を行ってみます。 gender カラムと address カラムでグループ化を行いデータの行数を取得します。

select gender, address, count(*) from user group by gender, address;

GROUP BY句を使ったグループ化(7)

指定した複数のカラムの値の組み合わせ毎にグループ化されてデータの行数が取得できました。

今回は count 関数を使って試してみましたが、他の関数を使用することでグループ毎に値の合計値を出したり平均値を出したりすることができます。

グループ後のデータに条件を設定する

グループ化を行う場合にも WHERE 句を使って対象となるデータの条件設定を行うことができます。

SELECT カラム名, ... FROM テーブル名 WHERE 条件式
  GROUP BY カラム名, ...;

この場合はまず WHERE 句に記述された条件式で取得するデータを絞り込んだ上でグループ化が行われます。

それに対してグループ化を行った上で、取得するグループを絞り込むために使用されるのが HAVING 句です。書式は次の通りです。

SELECT カラム名, ... FROM テーブル名
  GROUP BY カラム名, ... HAVING 条件式;

グループ化が行われた結果に対して条件式が適用されますので、HAVING 句の条件式に記述できるのはグループ化に指定したカラム名や、関数などを使ってグループ単位で集計した結果だけです。

それでは実際に試してみます。先ほど使用したテーブルを使います。次のようなデータが現在格納されています。

select * from user;

グループ後のデータに条件を設定する(1)

条件を設定せずに address カラムでグループ化を行いデータの行数を取得してみます。

select address, count(*) from user group by address;

グループ後のデータに条件を設定する(2)

それでは HAVING 句を使って count(*) の個数が 2 以上のデータだけを取得するようにしてみます。

select address, count(*) from user group by address having count(*) >= 2;

グループ後のデータに条件を設定する(3)

グループ化された後で取得したデータの中で条件式を満たすものだけが取得されました。このように HAVING 句を使用することで、グループ化した後のデータに対して条件式を設定することができるようになります。

-- --

グループ化を行う時に使用する GROUP BY 句の使い方、及びグループ化した後で絞り込みを行うために使用する HAVING 句について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。