VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
GROUP BY のない集計関数は、テーブル全体を 1 つのグループとして扱い、1 行を
返します。GROUP BY はまず行をグループに分けるため、グループごとに 1 行が得られ
ます。「映画は何本あるか」が「レーティングごとに映画は何本あるか」になるのは
こうしてです。
始める前に mysql -u root -p sakila でクライアントを開いてください。
GROUP BY の仕組み
GROUPING_COLUMN をその値がグループを定める列に、TABLE_NAME をテーブルに、
AGGREGATE_FUNCTION(COLUMN_NAME) を各グループについて計算したいものに置き換え
ます。
サーバーは行を、グループ化列の異なる値ごとに 1 つのバケットに振り分け、各
バケットに対して別々に集計関数を実行します。結果の行数は、異なる値の数と同じ
です。
GROUP BY は WHERE の後、ORDER BY の前に置きます。これは結果が定義される
順序でもあります。行をフィルタし、残ったものをグループ化し、それからグループを
並べ替えます。
例
- 値ごとに 1 行
rating には 5 つの異なる値があるため 5 グループで、5 つの件数を足すと 1,000 に
なります。行はアルファベット順ではなく ENUM の宣言順で出てきます。これは
SELECT DISTINCT のレッスンで説明しています。
- 2 つの列でグループ化する
2 つの列を指定すると、グループはそれぞれの値ではなく、異なる組み合わせになり
ます。
SELECT DISTINCT rating, rental_rate が返すのと同じ形に、各行の件数を付けた
ものです。
- グループ化の前に行をフィルタする
WHERE が先に実行されるため、件数はそれを通過した行に対するものです。
WHERE がそのグループの行をすべて取り除いたときだけです。
- 計算したものでグループ化する
グループ化列は列である必要はありません。任意の式が使え、エイリアスで名前を付けて
それでグループ化できます。
GROUP BY は選択リストのエイリアスを受け入れますが、WHERE は受け入れません。
レポートが月ごとにグループ化されるのはこうしてです。月を計算し、それでグループ化
します。
- 結合に対してグループ化する
グループ化が最も役立つのは、行が複数のテーブルから来るときです。これは各顧客の
支払いを数えます。
GROUP BY に last_name だけでなく customer_id も入って
いるのは、2 人の顧客が同じ姓を共有し得るため、それらを別々に数えたいからです。
選択したすべての列はグループ化されるか集計されなければならない
グループは多数の行です。グループ化列でもなく集計関数の中にもない列を求めるのは、 その多数の行のどれを表示するかをサーバーに尋ねることであり、サーバーに答えは ありません。デフォルトで有効なonly_full_group_by 設定が、サーバーに推測では
なくそう言わせるものです。
ERROR 1055 は解決できなかった列を名指しします。ここでは title です。出口は
3 つあり、どれが正しいかは意図によります。
- より細かいグループが欲しかったなら、その列を
GROUP BYに追加します。 - どれか 1 つの値でよいなら、
MIN(title)のような集計関数で包みます。 - 必要なかったなら、選択リストから外します。
only_full_group_by を無効にすると、同じクエリは実行され、サーバーが選んだ
プラン次第で任意のタイトルを返します。
MySQL の GROUP BY のパフォーマンスのガイドでは、この
設定と、意図的に任意の行を求める方法である ANY_VALUE() を扱っています。
GROUP BY は順序を約束しない
グループは、サーバーが都合の良いと判断した順序で返ってきます。ここのすべての例にORDER BY があるのは、LIMIT と同じく、それが順序を固定する
唯一の方法だからです。
まとめ
- 全体で 1 行ではなく、異なる値ごとに 1 行の結果を得るには
GROUP BYを使います。 - 複数の列を指定すると、異なる組み合わせごとにグループができると考えてください。
WHEREはグループ化が起きる前に行をフィルタすると考えてください。ERROR 1055は、グループ化も集計もされていない列と読んでください。- グループの順序が重要なときは
ORDER BYを追加します。
関連項目
- 集計関数 — グループごとに計算するもの
- HAVING — 作られた後のグループをフィルタする
- WITH ROLLUP — グループの下に合計行を追加する
- MySQL の GROUP BY のパフォーマンス — これが作り得る一時テーブル