LoginSignup
2
6

More than 5 years have passed since last update.

PG::GroupingError: ERROR: column "users.id" must appear in the GROUP BY clause or be used in an aggregate function

Last updated at Posted at 2017-07-30

はじめに

Ruby on Railsを使ってAPIを開発していたときに遭遇したPostgreSQLに関するエラーとその対処法をご紹介します。

やりたいこと

ある条件を満たすユーザに関する何らかの値の「平均値」、「合計値」、「合計ユーザ数」を返すメソッドを実装したい。

今回は年齢 (age) が20歳のユーザの得点 (score) の「平均値」、「合計値」、「合計ユーザ数」を返すメソッドを例にご紹介します。

仕様

対象のメソッド

class User < ActiveRecord::Base

  .
  .
  .

  def self.parameters()
    parameters = User.where(age: 20)
                     .select('COUNT(*) AS total_user,
                              ROUND(AVG(score), 1) AS average,
                              SUM(score) AS total_score')
    {
      average: parameters.first.average || '0.0',
      total_user: parameters.first.total_user,
      total_score: parameters.first.total_score || 0
    }
  end

  .
  .
  .

end

スキーマ

# == Schema Information
#
# Table name: users
#
#  age        :integer
#  created_at :datetime         not null
#  id         :integer          not null, primary key
#  score      :integer
#  updated_at :datetime         not null
#

どんなエラー?


PG::GroupingError: ERROR:  column "users.id" must appear in the GROUP BY clause or be used in an aggregate function

idGROUP BYしろ?

対処法

.order(nil)を追加すれば解決した。

class User < ActiveRecord::Base

  .
  .
  .

  def self.parameters()
    parameters = User.where(age: 20)
                     .select('COUNT(*) AS total_user,
                              ROUND(AVG(rate_score), 1) AS average,
                              SUM(rate_score) AS total_score')
                     .order(nil) # これを追加
    {
      average: parameters.first.average || '0.0',
      total_user: parameters.first.total_user,
      total_score: parameters.first.total_score || 0
    }
  end

  .
  .
  .

end

原因

parametersは要素が1つの配列になり、その後.firstでその要素を取得しています。
しかし、Railsは賢いため、parametersを取得する際に、.firstまでを1つのクエリとして最適化して処理してしまいます(多分)。
よって、「.firstをするにはオーダーされていないからダメだよ!」ということになっていました。
ということで、order(nil)を追加することでオーダーするつもりはないことをRailsに知らせてあげる必要があったみたいです。

結論

Railsは賢い()ので理解が微妙なまま開発を進めてはいけません。

2
6
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
2
6