グループ化したデータを取得する条件を設定する(HAVING句)

HAVING 句を指定すると GROUP BY 句によってグループ化されて取得したデータに関して、取得する条件を設定することができます。ここでは MySQL で HAVING 句を使ってグループ化したデータを取得する条件を設定する方法と、 WHERE 句と合わせて利用する場合の注意点などについて解説します。

※ GROUP BY 句の使い方については「データをグループ化する(GROUP BY句)」を参照されてください。

(Last modified: )

グループ化したデータを取得する条件を設定する

HAVING 句は GROUP BY 句によってグループ化が行われたデータに対して条件を指定してデータを絞り込む場合に使用します。使い方は次の通りです。

SELECT col_name1 [, col_name2 ...] FROM table_name
  GROUP BY col_name, ... HAVING where_condition

HAVING 句が記述されている場合、グループ化したデータを 1 件取得しようとするたびに条件式( where_condition )を評価して、結果が TRUE となった場合にデータを取得します。HAVING 句の条件式に記述できるのはグループ化に指定したカラム名や、関数などを使ってグループ単位で集計した結果だけです。

使い方は次のとおりです。

[例] グループ毎に price カラムの値平均を計算し、平均の値が 100 を超えるデータを取得
SELECT AVG(price) FROM goodslist GROUP BY category HAVING AVG(price) > 100;

※ AVG 関数はカラムに格納されている値の平均値を取得する関数です。詳細は「AVG関数 (指定のカラムに格納されている値の平均値を取得する)」を参照されてください。

-- --

それでは実際に試してみます。次のようなテーブルを作成しました。

create table report (branch varchar(10), name varchar(10), sales int);

グループ化したデータを取得する条件を設定する(1)

テーブルには次のようなデータを追加してあります。

insert into report values ('Tokyo', 'Yamada', 150);
insert into report values ('Osaka', 'Nishi', 280);
insert into report values ('Sapporo', 'Suzuki', 190);
insert into report values ('Nagoya', 'Honda', 240);
insert into report values ('Osaka', 'Tani', 120);
insert into report values ('Nagoya', 'Endou', 130);
insert into report values ('Tokyo', 'Kuroda', 300);
insert into report values ('Sapporo', 'Yoshida', 150);

グループ化したデータを取得する条件を設定する(2)

それでは branch カラムの値を基準としてグループ化を行い、グループ毎に sales カラムの値の平均値を取得します。

select branch, avg(sales) from report group by branch;

グループ化したデータを取得する条件を設定する(3)

HAVING 句を使って sales カラムの平均値が 200 以上のデータだけを取得するように変更してみます。

select branch, avg(sales) from report group by branch having avg(sales) >= 200;

グループ化したデータを取得する条件を設定する(4)

このように HAVING 句を使うことで、グループ化して取得したデータに対して条件式を設定することができます。

別名を割り当てて条件式の中で使う

AS 句を使用することでカラムに別名を割り当てることができますが、割り当てた別名を HAVING 句の条件式の中で使用することができます。( AS 句については「カラムに別名を付ける(AS句)」を参照されてください)。

先ほど作成したテーブルに対して branch カラムの値を基準としてグループ化を行い、グループ毎に sales カラムの値の平均値を取得しましたが、平均値に対して別名を割り当てるには次のように実行します。

select branch, avg(sales) as average from report group by branch;

別名を割り当てて条件式の中で使う(1)

割り当てた別名は HAVING 句の条件式の中で使用することができます。

select branch, avg(sales) as average from report group by branch having average >= 200;

別名を割り当てて条件式の中で使う(2)

WHERE 句と HAVING 句を同時に記述した場合

WHERE 句と HAVING 句を同時に記述した場合、まず WHERE 句で設定した条件を満たすデータだけを対象にグループ化が行われます。そしてグループ化したデータに対して HAVING 句で設定した条件を満たすデータだけを取得することになります。

それでは先ほど作成したテーブルに対して、 sales カラムの値が 150 以上のデータだけを対象にグループ化を行い、グループ毎に sale カラムの平均を取得し、その平均が 200 以上のものだけを取得してみます。

select branch, avg(sales) as average from report where sales >= 150 group by branch having average >= 200;

WHERE 句と HAVING 句を同時に記述した場合(1)

なお WHERE 句や GROUP BY 句をまとめて記述する順番は次の通りです。

SELECT col_name FROM table_name
    [WHERE where_condition]
    [GROUP BY col_name, ... [WITH ROLLUP]]
    [HAVING where_condition]

-- --

HAVING 句を使ってグループ化したデータを取得する条件を設定する方法について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

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