2011-08-03 8 views
4

私は、ユーザーを投稿に参加させて、表示可能な投稿を持つユーザーのみを取得するスコープを持っています。これはMySQLで動作しますが、PGはもっと厳しくなり、エラーが発生します。Rails/Postgres:GROUP BY句に列が表示されている必要があります

ユーザーモデル:

belongs_to :account 

scope :have_posts, joins(:posts).where('posts.visible => true').group('users.id') 

コントローラー:

@account.users.have_posts.each do |user| 
    # do stuff 
end 

がエラー:

(PGError: ERROR: column "users.account_id" must appear in the GROUP BY clause or be used in an aggregate function: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE ("users".account_id = 1) AND (recommendations.approved = true) GROUP BY users.id)

それは私明らかにドンとして@account.usersを呼ぶからです "users.account_id"(文句ですDB内のすべてのユーザーが必要です)。

どのように修正するのですか?

答えて

6

問題はGROUP BYです。これを使用すると、非集約フィールドを選択できないため、SELECT "users".* [...]は機能しません。 Postgresのドキュメントから:

In general, if a table is grouped, columns that are not used in the grouping cannot be referenced except in aggregate expressions.

このような何かが動作する可能性があり、厄介なものの:

1つの選択肢は、MAXまたはMINなどの集計関数を使用して、すべての選択したフィールドを指定することですが、これはおそらくになりますスコープはより長くて汎用性に欠けます。

0

これは、の条件ではありません。のデータがないため、joinsと表示されます。 IMHOははるかに読みやすく:

scope :have_posts, -> { 
    where(
    'EXISTS (SELECT 1 FROM posts p WHERE p.id = users.id AND visible = true)' 
) 
} 

Ruby 2とRails 3/4 ready。 PGオプティマイザはできるだけ早く実行するよう注意します。

関連する問題