データベース操作の際に、特定の基準を満たすデータのみを抽出したい状況はよくありますよね。そこで本記事では、データの絞り込み条件を指定する「HAVING」句について解説します。また、HAVING句と似たクエリであるWHERE句との違いも説明しますので、ぜひ参考にしてください。
HAVING句とは
SQLのHAVING句は、条件を指定するクエリで、抽出や更新の対象となるデータの絞り込む際に用いられます。たとえば、データを抽出する「SELECT」文と組み合わせて抽出するデータに条件を付けることで抽出対象を絞り込めたり、データを更新する「UPDATE」文と組み合わせてデータの更新対象を絞り込めたりします。
【基本構文】
SELECT文と組み合わせた場合の構文は次のとおりです。
SELECT フィールド名 FROM テーブル名 HAVING 条件
【サンプルテーブル】
HAVING句の具体的な使い方を解説していくにあたって、サンプルとして「テスト(test)」テーブルを用意しました。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
男子生徒のみを抽出してみましょう。
【実行コード】
SELECT * FROM test HAVING gender='男';
【実行結果】
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1004 | 佐藤 | 男 | 75 |
1006 | 田中 | 男 | 90 |
このように、HAVING句を扱えるようになれば、データベースに保存された膨大なデータの中から条件にあてはまるレコードだけを抽出したり、更新したりできるようになります。
お察しの方もいると思いますが、基本的には「WHERE」句と同じです。ただ、両者には明確な違いがあります。それは作用する順番です。
HAVING句をGROUP BY句と併用する場合は、GROUP BY句でグループ化したデータに特定の条件を適用し、それを満たす結果のみを抽出します。
一方で、HAVING句と同じく抽出条件を指定するクエリである「WHERE句」はGROUP BY句との併用時、データをグループ化する前の個別のレコードに条件を適用するもので、HAVING句とは条件を適用するタイミングが異なります。このように、同じ抽出条件を指定するクエリでも、データを事前に絞り込む「WHERE句」と、データをグループ化した後に条件を適用する「HAVING句」でフィルタリング手段が異なります。
HAVING句はどのような場面で使う?
条件文を使う場合、基本的には「WHERE」句を用いる人が多いのではないでしょうか?ではどういった場面で使うかというところについて言及します。それは、WHERE句ではできないタイミングで条件を適用させたい時です。先ほど説明しましたが、改めて両者の違いをおさらいしましょう。
「WHERE」句と「HAVING」句の違い
WHERE句とHAVING句は、どちらもデータをフィルタリングするための機能という点で共通しています。しかし、「GROUP BY」句と併用する場合、どの段階でフィルタリングを行うかというタイミングが大きく異なります。
「WHERE」句:「GROUP BY」句の実行前に条件が適用される
「HAVING」句:「GROUP BY」句の実行後に条件が適用される
つまり、「WHERE」句と「HAVING」句の間にある「GROUP BY」句が関わってこない場合は同じ挙動をしますが、「GROUP BY」句を併用する場合は挙動に違いが出てくるというわけです。
このように、SQLでは「WHERE」→「GROUP BY」→「HAVING」という実行順序があり、グループ化の前に任意の条件を満たさないレコードを省く場合は「WHERE」句を使い、グループ化後に任意の条件を満たさないグループを省く場合に「HAVING」句を使います。
引き続き先ほどのサンプルテーブルを使用します。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
両者の違いがわかりやすいよう、「WHERE」句でグループ化前に絞り込む方から説明します。
「WHERE」句でグループ化前に絞る場合
先ほどの「テスト」テーブルを用いて、生徒のうち、テストの点数が60点未満の生徒を除いた男女別の人数を表示させましょう。
【実行コード】
SELECT gender AS 性別,COUNT(gender) AS 人数 FROM test WHERE point>=60 GROUP BY gender;
【実行結果】
性別 | 人数 |
男 | 3 |
女 | 3 |
60点未満の土屋さんが除かれたことで、60点以上の生徒は男子が3名、女子が3名となりました。
「HAVING」句でグループ化後に絞る場合
「テスト」テーブルのうち、男女別でグループ分けした人数が3人以下のグループのみ表示させましょう。
【実行コード】
SELECT gender AS 性別,COUNT(gender) AS 人数 FROM test GROUP BY gender HAVING 4>COUNT(gender);
【実行結果】
性別 | 人数 |
男 | 3 |
4人以上のグループが除かれたことで、男子生徒のみが表示されました。
WHEREとHAVINGは併用できる?
HAVING句とWHERE句はクエリの実行タイミングが異なるため、併用することができます。
具体的なクエリの例を理解するために、先ほど用いた「テスト(test)」テーブルを参照します。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
生徒のうち、「テストの点数が65点以上の生徒」に絞り、男女別にグループ分けし、その人数が3人以上のグループだけを表示させましょう。
【実行コード】
SELECT gender AS 性別,COUNT(gender) AS 人数 FROM test
WHERE point>=65 //点数が65点以上の生徒だけ
GROUP BY gender //男女でグループ分け
HAVING COUNT(gender)>=3; //3人以上の生徒がいるグループだけ
【実行結果】
性別 | 人数 |
男 | 3 |
このように、WHEREとHAVINGを併用することで、より詳細な条件を設定してデータを抽出できます。
WHEREとHAVINGで同じ結果になるときはどちらを使う?
WHEREとHAVINGを使うなかで、どちらを使っても同じ結果になることもしばしばあります。そんなときは、なるべくWHEREを使いましょう。
その理由は、なんといってもWHEREのほうが実行速度が速いからです。
実際にクエリが実行されるとき、WHEREはGROUP BYの前に、HAVINGはGROUP BYの後に実行されると先ほど説明しました。この実行順序の違いによって両者の実行速度には顕著な差が出ます。
GROUP BYを使用することでテーブルをソートする処理などの演算が行われるのですが、これが処理速度に大きな影響を与えることになります。
GROUP BYより先にクエリが実行されるWHEREを使用した場合、ソートを行うよりも先に実行されます。一方でHAVINGを使用した場合はソートが行われたあとにクエリが実行されるため、パフォーマンスの低下を招く場合があります。
データベースが大きくなればなるほどこの差は大きく出てきます。そのため、WHEREで書けるところはWHEREを使用して、HAVINGが必要になる条件のときだけHAVINGを使用するといったように適切にクエリを使い分けるように心がけましょう。
まとめ
HAVING句を使用することで、大量のデータの中から特定の情報をピンポイントで抽出することができるようになります。データ分析やレポートなど、用途に合わせてHAVING句を活用してみてください。
以下では、SQLに関するさまざまな記事を取り上げています。SQLに関する疑問や興味がある方は、ぜひ併せて参考にしてみてください。
SQL関連記事
- RDBを操作するデータベース言語「SQL」とは?
- RDB以外のデータベース管理システム「NoSQL」とは?
- RDB管理システム「MySQL」とは?
- RDB管理システム「PostgreSQL」とは?
- RDB管理システム「SQL Server」とは?
- RDB管理システム「SQLite」とは?
- ブラウザ上でMySQLを管理できる「phpMyAdmin」とは?
- データを抽出する「SELECT」文
- データを追加する「INSERT」文
- データを削除する「DELETE」文
- データを更新する「UPDATE」文
- テーブル構造を変更する「ALTER TABLE」文
- 抽出条件を指定する「WHERE」句
- 抽出条件を指定する「HAVING」句
- 複数の抽出条件をまとめる「IN」句
- 重複レコードを除外する「DISTINCT」
- 抽出範囲を指定する「BETWEEN」演算子
- 抽出条件を満たすレコードの存在の有無を調べる「EXISTS」句
- レコード件数を取得する集計関数「COUNT」関数
- レコードをグループ化する「GROUP BY」句
- 抽出結果を並び替える「ORDER BY」句
- テーブル間のデータを結合する「JOIN」句
- 内部結合「INNER JOIN」句
- 抽出結果を統合して表示する「UNION」句
- データの曖昧検索「LIKE」句
- データの取得件数を制限する「LIMIT」句
- 条件分岐処理「CASE」式
- 「NULL」の扱い方
- 「主キー」とは?
- 「外部キー」とは?
SQLの勉強方法は?
SQLには、今回紹介したHAVING以外にも多くの構文があり、完全に習得し、自在にデータを扱えるようになるには多くの学習時間と実践の時間が必要になります。
特に、実践の時間については独学ではなかなか設けることができないものです。実践を交えてSQLを身につけたいと考えるのであれば、総合的な実践まで経験できるプログラミングスクールがおすすめです。
当サイトTECH MANIAでは、最短3か月で基礎から実践力・応用力まで身につけることのできるプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
独学でつまずいた方、一流のITエンジニアとしてスキルを高めていきたい方は必見です。
お問い合わせは以下のリンクからお進みください。