🐡

MysqlのONLY_FULL_GROUP_BY

2022/06/17に公開

MySQL 5.7以降、ONLY_FULL_GROUP_BYは初期状態で有効。

確認するSQLは以下の通り。

SELECT @@global.sql_mode;

参照
https://www.wakuwakubank.com/posts/414-mysql-sqlmode/

Mysql公式でONLY_FULL_GROUP_BYの項目を読んだけど、なんかしっくり来ない・・
https://dev.mysql.com/doc/refman/8.0/ja/group-by-handling.html

https://qiita.com/wakanayoshizawa/items/9fdca834076cb4c3389e
↑のコメント欄が分かりやすかった。

つまりGROUP BY使っている場合はSELECTするものを全部GROUP BYに書け

この書き方ですと、SELECT文で指定した全てのカラムをGroup Byに書きなさいと読めます。カラムを10個SELECTする場合はGROUP BYが10個書かないとダメという話に聞こえ、それは違います。
MySQLが言っている「non-aggregated column」がどういったものかについて、例を出します。
ユーザーテーブルがあって、例えばそれをドメインでGROUP BYするとします。SQLはこんな感じです。

select 
   id,
   substring(email,locate('@',email)) as domain, 
   count(*) as cnt 
from 
   user 
group by 
   domain

これを実行すると、IDカラムがnon-aggregate columnだからダメだとエラーになります。ドメインで集約された結果、あるドメインで10人のユーザーが存在したとします。この場合、IDカラムは非集約になります。ドメインで集約したらユーザーIDは集約の対象にはなり得ないからです。適当な値を返すしかなくなります。恐らくは最古のレコードのIDになるでしょうけど。

なので、GROUP BYを使っておいてキチンと集約された結果に反するSQLはダメというのが「nonaggregated column」の意味する所です。

「ONLY_FULL_GROUP_BY エラー」で検索すると、GROUP BYで指定したカラム以外をSELECTで指定しているからだと言う内容が多かったけど正しくは集計カラムを指定していないからだと言うことがわかりました。

上記のSQLの例で言うと

count(*) as cnt 

がエラーにならないのが分かりやすい例でした。

エラー回避の方法は以下のブログがわかりやすかったです。
https://blog.capilano-fw.com/?p=7001

Discussion