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)
を差し込むことで対応する。