2011-09-28 70 views
3

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

从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和聚合函数结果一个完整的模型,返回的数据(最有可能)不匹配实际模型(行)。

回答

1

您必须将您的select子句扩展为您希望检索的所有列。或

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

感谢玛丽安 - 但是这会产生无效的SQL。默认情况下MySQL对此感到满意,但不是PostgreSQL。 SELECT子句中的值不存在于GROUP BY或聚合函数中。 – dkam

+0

第一句话是正确的。非常感谢。 – dkam

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) 

免责声明:红宝石语法是外语给我。