LoginSignup
8
4

More than 5 years have passed since last update.

Rails && MySQL >= 5.7 でERROR 1055 (42000)となる原因と対処3Way

Last updated at Posted at 2017-04-18

ActiveRecordで集計系Scopeを組んでいるときに、エラーに遭遇

ERROR 1055 - Expression #5 of SELEC list is not in GROUP BY clause and contains nonaggregated column '***' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

sql_mode=only_full_group_by とな

SQLモードを調べる

mysql> select @@SESSION.sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                                                                        |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)
  • ちなみにSQLモードとは、SQL実行時のルールのようなものです。 上にある STRICT_TRANS_TABLESはINSERT/UPDATE時の型チェックを厳しくして実行を中止したりします。

ONLY_FULL_GROUP_BYは、GROUP BYで集計するとき、SELECT句やORDER BY句で指定されるカラムがGROUP BY句に含まれていなければならないというルール。

どうやら、MySQL5.7から”ONLY_FULL_GROUP_BY”は、デフォルトの設定となった模様

MySQL 5.7.5 and up implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default),
-- MySQL5.7 Reference

MySQLの場合、これ迄は同様の書き方でもエラーは出なかった。

設定変更で対応

ていうかそもそもORDER BY句自体が必要ないんですよね、集計関数だから。
どうやらModel側で default_scopeに ->{ order(id: :desc) } が入る(プロジェクト設定の)ため、これを外せる(モデルなの)なら外せば良い。

できないのであれば、my.cnfのONLY_FULL_GROUP_BYを外すという選択肢もありますが、
他のRDBMSでは元々SQLとしてエラーになる書き方であるからして、ここは残しておくべきかと思います。

コード書き換えで対応

よって個別の対応策としては、Modelのscope側に

scope :active_count_by_category, lambda {|category|
  active
  .where(:category_id, category.id)
  .group(:category_id)
  .reorder(nil)
  .count(:id)
}

のように .reorder(nil)を差し込むことで対応する。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4