使用Arel按频率订购记录

时间:2011-09-28 04:34:18

标签: ruby-on-rails postgresql activerecord group-by arel

如何检索一组按Arel中的计数排序的记录?我有一个模型可以跟踪产品的视图数量。我想在过去的Y天找到X最常见的产品。

从MySQL迁移到PostgreSQL时出现了这个问题,因为MySQL对它接受的内容有点宽容。来自View模型的此代码适用于MySQL,但不适用于PostgreSQL,因为输出中包含非聚合列。

scope :popular, lambda { |time_ago, freq|
  where("created_on > ?", time_ago).group('product_id').
    order('count(*) desc').limit(freq).includes(:product)
}

这是我到目前为止所得到的:

View.select("id, count(id) as freq").where('created_on > ?', 5.days.ago).
  order('freq').group('id').limit(5)

但是,这会返回模型的单个ID,而不是实际模型。

更新 我跟着去了:

select("product_id, count(id) as freq").
  where('created_on > ?', time_ago).
  order('freq desc').
  group('product_id').
  limit(freq)

在反思中,当结果由GROUP BY和聚合函数结果组成时,期望完整模型并不合乎逻辑,因为返回的数据(很可能)不匹配实际模型(行)。

2 个答案:

答案 0 :(得分:1)

您必须使用要检索的所有列扩展select子句。或

select("views.*, count(id) as freq")

答案 1 :(得分:1)

SQL将是:

SELECT product_id, product, count(*) as freq
 WHERE created_on > '$5_days_ago'::timestamp
 GROUP BY product_id, product
 ORDER BY count(*) DESC, product
 LIMIT 5;

从您的示例推断,它应该是:

View.select("product_id, product, count(*) as freq").where('created_on > ?', 5.days.ago).
  order("count(*) DESC" ).group('product_id, product').limit(5)

免责声明:Ruby语法对我来说是一种外语。