Mysql5.6から5.7にしたらONLY_FULL_GROUP_BYがオンになってエラーなったので、なおした
これはなに
Mysql5.7でONLY_FULL_GROUP_BYがデフォルトでオンになってて、それに関連してGroup byでテキトーにやってたところにエラーが出た。
以下、エラー出た箇所と対処を書く。
(ちなみに、上記設定をdisableにすることもできるけどnot recommend)
なにやったか
まず元々どうなってたか書く。 たとえば、簡単にtableを、
+-----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | movieid | varchar(255) | YES | UNI | NULL | | | userid | varchar(255) | YES | | NULL | | | lang | varchar(255) | YES | | NULL | | | country | varchar(255) | YES | | NULL | | | image | varchar(255) | YES | | NULL | | | duration | int(11) | YES | | NULL | | | created | int(11) | YES | | NULL | | | maxview | int(11) | YES | | NULL | | | totalview | int(11) | YES | | NULL | | +-----------+--------------+------+-----+---------+----------------+
でここから、
mysql > select * from table_name where country = 'us' and duration >= 2000 and created >= OO and created <= OO group by userid having count(userid) >= 1 ;
とする。で、たとえば、having以下の条件を変えて、countryがusでdurationが2000以上の配信のうちcreatedがOOからOOまでの期間で、1回以上配信してる人、3回以上配信してる人みたいなのを出そうとしてた。
で、これで条件にあるデータが返ってきてたけど、よく考えると、同じユーザーでもmovieidは違うので、ちょっときもいけど、勝手にidが一番小さいやつを選んで出力してた。
ONLY_FULL_GROUP_BYだと怒られる。
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db_name.table_name.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Roland Bouman's blog: MySQL 5.7.5: GROUP BY respects functional dependencies!
MySQL :: MySQL 5.7 Reference Manual :: 12.20.3 MySQL Handling of GROUP BY
てことで、明示的に指定する。さらに上記のやり方ではidが小さい特定のデータを取ってたけど、そのユーザーのavg情報を出すことにする。
mysql > select userid, lang, country, image, avg(duration), avg(maxview), avg(totalview) from table_name where country = 'us' and duration >= 2000 and created >= OO and created <= OO group by userid, lang, country, image having count(userid) >= 1 ;
一意になるcolumnをきちんとgroup byに明示的に書いてあげる。selectにもしかり。で、すっきりした出力結果になる。