かみぽわーる

kamipo's blog

MySQL 5.7のONLY_FULL_GROUP_BYはちょっと進化してた

このエントリはMySQL Casual Advent Calendar 2015の14日目です。

TL;DR

MySQL 5.7ではデフォルトONLY_FULL_GROUP_BYが有効である。MySQL 5.7.5からONLY_FULL_GROUP_BYが有効のとき

  • GROUP BY句のカラムと関数従属性のあるカラムはSELECT句に書けるようになった😤
  • ORDER BY句のカラムはDISTINCTのカラムリストに含めなければいけなくなった😣
  • ONLY_FULL_GROUP_BYを無効にしなくてもHAVING句のalias拡張が使えるようになった😆

GROUP BY句のカラムと関数従属性のあるカラムはSELECT句に書けるようになった

[mysqlcasual] > CREATE TABLE users (id int unsigned auto_increment primary key, name varchar(255));
Query OK, 0 rows affected (0.03 sec)

[mysqlcasual] > CREATE TABLE friends (user_id int unsigned, friend_id int unsigned);
Query OK, 0 rows affected (0.04 sec)

以下のクエリはu.nameがGROUP BY句に含まれてなくて集合関数にもかけられてないけどf.user_idに関数従属しているので5.7では実行できます!

[mysqlcasual] > SELECT f.user_id, u.name, COUNT(*) FROM friends f JOIN users u ON f.user_id = u.id GROUP BY f.user_id;
Empty set (0.00 sec)

残念ながら5.6ではONLY_FULL_GROUP_BYが有効だとエラーです。

[mysqlcasual] > SELECT f.user_id, u.name, COUNT(*) FROM friends f JOIN users u ON f.user_id = u.id GROUP BY f.user_id;
ERROR 1055 (42000): 'mysqlcasual.u.name' isn't in GROUP BY

ORDER BY句のカラムはDISTINCTのカラムリストに含めなければいけなくなった

とにかくそういうことらしいです。他のが便利になる系なのに対してこれは既存のクエリに影響が出る系なので5.7にアップグレードして既存のクエリに影響があるか確認しておく必要があります。ちなみにActiveRecordというORマッパーは余裕でDISTINCTついてるクエリにORDER BYつくので滅茶苦茶影響がある。とにかくこれを一日も早くマージしてほしい。

github.com

ONLY_FULL_GROUP_BYを無効にしなくてもHAVING句のalias拡張が使えるようになった

これもとにかくそういうことです!

[mysqlcasual] > SELECT user_id, COUNT(*) c FROM friends GROUP BY user_id HAVING c = 1;
Empty set (0.00 sec)

以上、MySQL 5.7のONLY_FULL_GROUP_BYはちょっと進化してました!