外部キーのグループ化で、地味に躓いたので記事としてまとめます!
問題
GROUP BY句で外部キーを指定して、インスタンスを取り出そうとするとエラーが起きました。
現象
①
groupメソッドで、外部キーであるオフィスIDを指定し、条件に該当するインスタンスを複数得ることができます。
ここまではエラーは発生しません。
User.group(:office_id).select(:office_id)
User Load (9.7ms) SELECT `users`.`office_id` FROM `users` GROUP BY `users`.`office_id` LIMIT 11
=> #<ActiveRecord::Relation [#<User id: nil, office_id: 1>, #<User id: nil, office_id: 3>, #<User id: nil, office_id: 4>, #<User id: nil, office_id: 6>, #<User id: nil, office_id: 7>, #<User id: nil, office_id: 8>, #<User id: nil, office_id: 9>, #<User id: nil, office_id: 10>, #<User id: nil, office_id: 11>, #<User id: nil, office_id: 12>, ...]>
②
次に、インスタンスを取り出そうとすると、この段階でエラーが発生する。
User.group(:office_id).select(:office_id).first
User Load (8.9ms) SELECT `users`.`office_id` FROM `users` GROUP BY `users`.`office_id` ORDER BY `users`.`id` ASC LIMIT 1
Traceback (most recent call last):
1: from (irb):23
ActiveRecord::StatementInvalid (Mysql2::Error: Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'rd_web_office_app.users.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by)
調査
エラーが起きた時のSQLをみていきます。
SELECT `users`.`office_id` FROM `users` GROUP BY `users`.`office_id` ORDER BY `users`.`id` ASC LIMIT 1
→意図せず、デフォルトでusersテーブルの主キーである、IDでsortしようとしていました。
ORDER BY `users`.`id`
回避方法
明示的に、値の存在する外部キーでsortすることで、インスタンスを取り出すことができました!
User.group(:office_id).select(:office_id).order(:office_id).first
User Load (7.6ms) SELECT `users`.`office_id` FROM `users` GROUP BY `users`.`office_id` ORDER BY `users`.`office_id` ASC LIMIT 1
=> #<User id: nil, office_id: 1>
最後に
挙動としては、デフォルトで主キーsortされることでエラーになっていました。
あくまで推定でしかないので、この辺りに詳しい方がいれば教えていただきたいです!