テーブル名:商品一覧
商品名,販売単価,仕入単価
品目A,1000,700
品目B,2000,1400
品目C,3000,2100
品目D,1000,700
品目E,2000,1400
品目F,1000,700
…
というテーブルがあるとして、ここから、販売価格でGROUP BYする。
SELECT `販売価格`,COUNT(*)
FROM `商品一覧`
GROUP BY `販売価格`
結果は
販売単価,数
1000,3
2000,2
3000,1
となる。
ここで、
SELECT `商品名`,`販売価格`,COUNT(*)
FROM `商品一覧`
GROUP BY `販売価格`
としてしまうとエラー。
MySQLではエラーとはならずに通ってしまう(※)が、このSQL文に問題があることはすぐに分かる。
商品名,販売単価,数
ア,1000,3
イ,2000,2
ウ,3000,1
アは販売単価が1,000円の集合だが、販売単価が1,000円の商品は、品目A、品目D、品目Fの3商品がある。
で、アには、その内のどれを表示すればいいのか?
イは販売単価が2,000円の集合だが、販売単価が2,000円の商品は、品目B、品目Eの2商品がある。
で、イには、その内のどれを表示すればいいのか?
ウは販売単価が3,000円の集合だが、販売単価が3,000円の商品は、品目Cの1商品だけ。
ウには品目Cを表示すれば済むが、その後品目Gが追加され、その販売単価が3,000円だったら?
GROUP化クエリは、GROUP化したそのGROUP毎に1つにまとめてしまうため、その中身を全て表示することはできない。
GROUP BYを使う時、SELECT句に書ける列名は、GROUP BY句で指定した列名(集約キーという)だけである。
※ MySQLとSQLiteでは、エラーとはならず通ってしまう。
では、上記のアには何を表示するか、だが、実は、これといった決まりがない。
GROUP BY 部から省略したカラムがグループ内で一定していない場合は、この機能を使用しないでください。
サーバはいかなる値もグループから自由に戻すことができ、すべての値が同じでない限り、結果は不確定です。
11.11.3. 非常時フィールドとの GROUP BY および HAVING
つまり、
商品名,販売単価,数
品目A,1000,3
となることもあれば、
商品名,販売単価,数
品目D,1000,3
となることもあれば、
商品名,販売単価,数
品目F,1000,3
となることもあるということ。
参考:SQLアンチパターン 155ページ 第14章 アンビギュアスグループ(曖昧なグループ)
オライリージャパン
売り上げランキング: 12,496
これは非常に危険であるので、エラーではじいてくれた方がいいかもしれない。
また、問題のないSQL文、
SELECT `販売価格`,COUNT(*)
FROM `商品一覧`
GROUP BY `販売価格`
で得られた結果
販売単価,数
1000,3
2000,2
3000,1
だが、この並び順はランダム。
販売単価,数
3000,1
2000,2
1000,3
となるかもしれないし、
販売単価,数
2000,2
1000,3
3000,1
となるかもしれない。
オライリージャパン
売り上げランキング: 12,496