ruby-on-rails - rails : three most recent comments with unique users

标签 ruby-on-rails ruby sqlite postgresql activerecord

我应该在命名范围 :by_unique_users 中放入什么,以便我可以执行 Comment.recent.by_unique_users.limit(3),并且每个用户只获得一个评论?

class User
  has_many :comments
end

class Comment
  belongs_to :user
  named_scope :recent, :order => 'comments.created_at DESC'
  named_scope :limit, lambda { |limit| {:limit => limit}}
  named_scope :by_unique_users
end

在 sqlite named_scope 上:by_unique_user, :group => "user_id"有效,

但在部署在生产环境中的 postgres 上让它变得异常 PGError: ERROR: column "comments.id"must appear in the GROUP BY clause or be used in an aggregate function

最佳答案

Postgres 在处理 GROUP BY 的方式上不同于 MySQL 和 SQLite。从本质上讲,它非常严格。假设您有。

id name
1  foo
2  bar
2  baz

然后您将执行 GROUP BY id。 MySQL 假设您只想删除除名字以外的所有内容。所以它会产生。

id name
1  foo
2  bar

但是,在这种情况下,Postgres 不会猜测分组方法。它需要关于您希望如何对其他列进行分组的具体说明。为此,它提供了所谓的聚合函数,在这种情况下,您正在寻找一个函数,该函数需要一组函数中的第一个。我找不到执行此操作的函数,但也许 min()max() 可以作为一个函数。在这种情况下,您需要使用 :select => 'min(comments.id), min(comments.some_other_column)',并且您应该对除 user_id 之外的每一列执行此操作。然后你可以毫无问题地使用 :group => 'user_id'。

顺便说一句,min()max() 接受字符串,而不仅仅是数字,因此它们适用于任何列。如果你真的想要先行,那么谷歌搜索“postgres aggregate first”来寻找一些实现,或者使用postgres数组。尽管这些会破坏与 mysql 和 sqlite 的兼容性。

更新

另一方面,如果获取最近的评论不是太昂贵,让 ruby​​ 处理唯一用户部分。

unique_comments = []
Comment.recent.each do |comment|
  unless unique_comments.find{|c| c.user_id == comment.user_id}
    unique_comments << comment
  end
  break if unique_comments.size > 2
end

现在您最多有 3 条来自不同用户的评论。

关于ruby-on-rails - rails : three most recent comments with unique users,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2901480/

相关文章:

ruby-on-rails - 稍后在 Perform_later ActiveJob 上设置 stub

python - 在 NULL 列中添加值

ruby-on-rails - 为什么环境数据库的默认值不是同一个开发环境?

html - 为什么这个 formtastic CSS 不会在我的 Rails 3 应用程序中覆盖?

mysql - 开放地理数据库 : migrate mySQL data to postgreSQL

ruby-on-rails - 在 RAILS 中单击后退按钮时禁用 Flash 消息而不禁用缓存

ruby - 将 BigDecimal 转换为 String 时如何增加小数位数?

android - Android 2.1 和 2.2 之间的 SQLite 差异

php - 为什么我可以在 PHP 中的 SQLite 数据库上使用 SELECT 而不是 INSERT?

ruby-on-rails - 如何在 "assigns"之后访问 "render :template => ..."?