ハードディスクメンテナンス ブログ

投稿記事数7,500以上!PC,カメラ,オーディオ,ラジオ,航空,旧ゲームなど

MySQLに於けるGROUP BYでのミス(集約キー以外を書いてしまう)

   


テーブル名:商品一覧
商品名,販売単価,仕入単価
品目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句で指定した列名(集約キーという)だけである。

MySQLSQLiteでは、エラーとはならず通ってしまう。
では、上記のには何を表示するか、だが、実は、これといった決まりがない。

GROUP BY 部から省略したカラムがグループ内で一定していない場合は、この機能を使用しないでください。
サーバはいかなる値もグループから自由に戻すことができ、すべての値が同じでない限り、結果は不確定です。

11.11.3. 非常時フィールドとの GROUP BY および HAVING

つまり、

商品名,販売単価,数
品目A,1000,3

となることもあれば、

商品名,販売単価,数
品目D,1000,3

となることもあれば、

商品名,販売単価,数
品目F,1000,3

となることもあるということ。

参考:SQLアンチパターン 155ページ 第14章 アンビギュアスグループ(曖昧なグループ)

スポンサーリンク
SQLアンチパターン
Bill Karwin
オライリージャパン
売り上げランキング: 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

となるかもしれない。

SQLアンチパターン
Bill Karwin
オライリージャパン
売り上げランキング: 12,496


sha-bc@336×280

アマゾン(タイムセール)




sha-bc@336×280

アマゾン(タイムセール)


  関連記事

ディスク
[GParted] CF-R6のSWAP領域(linux-swap)の拡大操作 [Ubuntu]

SSDに換装したCF-R6だが、メモリーを増設しない場合、512MB(内蔵分)と …

Ubuntu
Ubuntu(14.04 LTS)の電源の統計一覧とバッテリーの劣化 [CF-VZSU49,CF-R6,CF-R7,CF-R8]

Linuxは標準で、ここまで細かい電源の情報を得ることができる。 Ubuntuな …

CF-R6
CF-R6は、遅杉且熱杉流!危険杉流「ファンレス」PC

灼熱波動拳並(ふンッ! by 豪鬼 スパIIX)に熱い、パナソニック(旧松下電器 …

no image
(在庫僅少)激安サーバー2機種、Linuxを入れてファイルサーバーやMySQLの学習用に!(富士通とHP)

2万円以下の激安サーバーを紹介しよう。 富士通 PRIMERGY MX130 S …

no image
クエリに対して複数コアを使いこなさない問題(MySQL)

3コアのCPUに換装したDBサーバーであるが、重いクエリを発行した場合、複数コア …

idを詰める(連番を振り直す)方法
[MySQL] idを詰める(連番を振り直す)方法

数分毎に定期的にログを取得するようなプログラムを書き、DBに格納し始める。 だが …

no image
Apache Server Information の設定 (Apache2.2.22 ,Debian7.4)

Apache/2.2.22 (Debian7.4) ローカルの試験サーバーのIP …

E3110
DBサーバーのハードウェア換装(Debian7.4,MySQL5.5.35) Xeon E3110

試験データベースサーバー(DBサーバー)を入れ替えた。 Debian7.4(64 …

no image
(NTP)サーバーの時刻自動調整(Debian7.4)

サーバーの内蔵時計は、一度合わせてもずれていく(パソコンでも同様)。 時刻がずれ …

no image
PowerEdgeT105のCPU換装(2コアから3コアに)

DELLのサーバーであるPowerEdgeT105のCPUを ①Athlon64 …