メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
GROUP BY はグループごとに 1 行を返し、全体の行は返しません。WITH ROLLUP は その行を追加し、複数の列でグループ化したときはその間の小計も追加します。2 つ目の クエリを実行して自分で数を足し合わせる手間を省きます。 始める前に、mysql -u root -p sakila でクライアントを開いてください。

WITH ROLLUP の仕組み

GROUPING_COLUMN をグループを定義する列に、TABLE_NAME をテーブルに、 AGGREGATE_FUNCTION(COLUMN_NAME) をグループごとに計算するものに置き換えます。 WITH ROLLUP は GROUP BY 句の末尾に置きます。 サーバーは通常のグループを返し、次に、あるグループ化列を脇に置いてその集約が 全体を対象とする追加の行を返します。脇に置いた列には NULL を入れるので、それで それらの行を見分けられます。

例

  1. 合計行を追加する

5 行ではなく 6 行です。最後の行はレーティングがあるべき場所に NULL があり、 その件数はテーブル全体です。

  1. 小計も

2 つの列でグループ化すると、1 番目の列の値ごとの小計と、次に総合計が得られます。
行は、どの列が NULL かで読みます。G / NULL / 3 は、すべての料金にわたる G の小計です。NULL / NULL / 10 は総合計で、185 分の映画が 10 本あることと 一致します。 ロールアップの行は、一番下にまとめられるのではなく、それが要約するグループの 後に続くため、結果は上から下へレポートとして読めます。

ロールアップの NULL を本物の NULL と見分ける

ロールアップの行の NULL は「この列のすべての値」を意味します。データ内の NULL は「値が記録されていない」を意味します。両者は同じように表示されるため、NULL になりうる列では、見ただけでは 2 つを区別できません。 GROUPING() がこの問いに直接答えます。その行でその列が脇に置かれたときは 1 を、 それ以外は 0 を返します。
Sakila では rating が NULL になることはないため、ここでは 2 つの問いの答えは 同じです。実際に NULL を保持する列では、rating IS NULL のテストは両方の種類の 行を捕まえ、GROUPING(rating) = 1 はロールアップだけを捕まえます。

ORDER BY は合計を動かし、並び順を変える

上の例に ORDER BY がないのは意図的です。WITH ROLLUP は各ロールアップ行を それが要約するグループの直下に置き、並べ替えはその配置を捨ててしまいます。
2 つのことが動きました。総合計が先頭に並び替えられました。NULL はすべての 実際の値より前に並ぶためです。そして、レーティングが GROUP BY が示した ENUM の宣言順ではなくアルファベット順で出てきました。ロールアップ 結果の並べ替えはテキストとして並べ替えるためです。 ですから、どちらが欲しいかを決めてください。グループの下に小計が並ぶレポート として読むには ORDER BY を付けず、付けるなら、ロールアップの行が並べ替えに よって置かれる場所に落ち着くことを受け入れます。

ロールアップの行にラベルを付ける

NULL の列はレポートに欲しいものではありません。COALESCE は NULL でない最初の 引数を返すため、代わりにそこに言葉を入れます。
これは読みやすく、ここで安全なのはデータ内の rating が NULL になることが ないからにすぎません。NULL になりうる列では、COALESCE は本物の欠損値に合計の ラベルを付けてしまうため、代わりにテストで GROUPING() を使ってください。

まとめ

  • 小計と合計の行を得るには、GROUP BY の末尾に WITH ROLLUP を追加します。
  • グループ化列の NULL は「この列のすべての値」として読みます。
  • 複数の列でグループ化すると、先行する各列の値ごとに小計が得られると考えてください。
  • ロールアップの行とデータが NULL の行を見分けるには GROUPING(column) を使います。
  • ORDER BY はロールアップの行を動かし、ENUM をテキストとして並べ替えると考えてください。

関連項目