MySQL GROUP BY 句と HAVING 句の例
⚡ スマートサマリー
SQLのGROUP BY句とHAVING句は、詳細な行を要約レポートに変換します。GROUP BY句は、同じ値を持つ行をグループごとに1行にまとめ、HAVING句は、COUNTなどの集計関数を適用した後に、それらのグループをフィルタリングします。

SQLのGROUP BY句とは何ですか?
GROUP BY 句は、次の目的で使用される SQL コマンドです。 同じ値を持つ行をグループ化するこれはSELECT文の中に記述され、通常は集計関数と組み合わせてデータベースから要約レポートを作成するために使用されます。
それがその機能です。 データを要約する データベースに格納されているデータ。GROUP BY句を含むクエリはグループ化クエリと呼ばれ、グループ化された項目ごとに1行を返します。
SQL GROUP BY 構文
句の目的が明確になったところで、基本的なグループ化クエリの構文を見てみましょう。
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
Pr_media
- SELECT文…」は標準です SQL 選択 コマンドクエリ。
- グループ化 列名1」はグループを実行する節ですping column_name1に基づきます。
- [, column_name2, …]」はオプションであり、グループが他の列名である場合にそれを表します。ping 複数の列に対して実行されます。
- [条件あり]」はオプションであり、GROUP BY句の影響を受ける行を制限するために使用されます。これは、 WHERE句ただし、グループが適用される場合を除きます。ping.
グロウping 単一列の使用
SQLのGROUP BY句の効果を最も簡単に確認する方法は、グループ化されていないクエリとグループ化されたクエリを比較することです。まずは、メンバーテーブル内のすべての性別エントリを返すシンプルなクエリから始めましょう。
SELECT `gender` FROM `members`;
| 性別 |
|---|
| 女性 |
| 女性 |
| 男性 |
| 女性 |
| 男性 |
| 男性 |
| 男性 |
| 男性 |
| 男性 |
9行が返され、すべての値が重複しています。性別ごとに一意の値を取得したいとします。以下のクエリは、GROUP BY句を追加します。
SELECT `gender` FROM `members` GROUP BY `gender`;
上記のスクリプトを実行すると、 MySQL ワークベンチ myflixdb に対して実行すると、次の結果が得られます。
| 性別 |
|---|
| 女性 |
| 男性 |
テーブルには性別が2種類しかないため、返された行は2行のみであることに注意してください。GROUP BY句は「男性」のメンバーをすべてグループ化して1行にまとめ、同様に「女性」のメンバーについても1行にまとめています。
グロウping 複数列の使用
グロウping 1つの列だけで集計するのは、実際のレポート作成には粗すぎる場合が多いです。GROUP BY句は、カンマで区切られた列のリストを受け付け、それらの値の組み合わせによって各グループを定義します。
映画のcategory_idの値と、それぞれの映画が公開された年の一覧を取得したいとします。まず、このシンプルなクエリの出力結果を見てみましょう。
SELECT `category_id`, `year_released` FROM `movies`;
| カテゴリ ID | リリース年 |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
強調表示された行は、結果に重複が含まれていることを示しています。同じクエリをGROUP BY句付きで実行すると、重複が削除されます。
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
上記のスクリプトを実行すると、 MySQL myflixdbに対するWorkbenchの実行結果は、以下に示すとおりです。
| カテゴリ ID | リリース年 |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
GROUP BY句はcategory_idとyear_releasedの両方に対して動作し、 ユニーク 行。2007年のカテゴリ6の重複した2つの行は1つに統合されました。
経験則: カテゴリIDが同じでもリリース年が異なる場合、その行は一意のものとして扱われます。カテゴリIDとリリース年が複数の行で同じ場合、それらの行は重複とみなされ、そのうちの1つだけが表示されます。
グロウping および集計関数
重複を削除することは便利ですが、グループ化の真の力はping ペアになっているときに表示されます 集計関数集計関数は、各グループに対して 1 つの値を計算します。COUNT は行数をカウントし、SUM は値を加算し、 AVG、MIN、およびMAXはスプレッドを表します。
データベース内の男性会員と女性会員の総数を取得したいとします。以下のスクリプトはそれを実現します。
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
上記のスクリプトを実行すると、 MySQL myflixdb に対して Workbench を実行すると、以下の結果が得られます。
| 性別 | COUNT(`membership_number`) |
|---|---|
| 女性 | 3 |
| 男性 | 6 |
行は性別ごとにグループ化され、各グループ内の行数はCOUNT集計関数によってカウントされます。9つのメンバーレコードは2つの要約行に集約されます。
HAVING句を使用したクエリ結果の制限
グロウpingテーブルのすべての行に対して常に条件が必要なわけではありません。レポートを特定の条件に限定する必要がある場合もあり、そのためには HAVING 句を使用します。
映画のカテゴリIDが8のすべての公開年を知りたいとします。以下のスクリプトでその結果が得られます。
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
上記のスクリプトを実行すると、 MySQL myflixdbに対するWorkbenchの実行結果は、以下に示すとおりです。
| 映画ID | タイトル | ディレクター | リリース年 | カテゴリ ID |
|---|---|---|---|---|
| 9 | Honey moonERS | ジョン・シュルツ | 2005 | 8 |
| 5 | ダディーズ・リトル・ガールズ | NULL | 2007 | 8 |
HAVING条件に該当するのは、カテゴリIDが8の映画のみです。
警告: MySQL 5.7以降では、デフォルトでONLY_FULL_GROUP_BYモードが有効になり、そのモードでは、movie_id、title、directorがグループ化も集計もされていないため、GROUP BY句を含むSELECT *は拒否されます。運用環境では、グループ化された列に明示的に名前を付けてください。例: SELECT category_id, year_released FROM movies GROUP BY category_id, year_released HAVING category_id = 8;
WHERE、HAVING、GROUP BY、ORDER BY
初心者は、これら 4 つの節を混同しがちですが、これらはすべて結果セットを形成します。違いは を特定いたします。 MySQL それらを適用する際、WHERE は行がグループ化される前に実行され、HAVING はグループ化された後に実行され、ORDER BY は最後に実行されます。
| 句 | 何それがありません | 実行時 | 集計関数を受け入れます |
|---|---|---|---|
| NeoCity | グループの前に個々の行をフィルタリングしますping. | GROUP BYの前に | いいえ |
| グループ化 | 同じ値を持つ行をグループごとに1行にまとめます。 | どこで | 適用されない |
| HAVING | GROUP BYによって生成されたグループをフィルタリングします。 | GROUP BYの後 | はい、例えば HAVING COUNT(*) > 2 の場合 |
| ORDER BY | 前の句を通過した行をソートします。 | 最後 | はい、集約エイリアスはソート可能です。 |
実質的な影響はパフォーマンス上の問題です。WHERE句によるフィルタリングでは、グループより前の行が削除されます。ping 作業が開始されるため、集計結果に依存しない条件は、HAVING ではなく WHERE に含めるべきです。
