按关联表中行的频率排序

时间:2014-12-22 16:10:51

标签: sql ruby-on-rails ruby ruby-on-rails-3 postgresql

我有2张桌子。产品和商店。产品属于商店。

我想按照上个月创建的降序排序商店。到目前为止,我有......

Product.where("created_at > ?", 1.month.ago).group_by { |p| p.store }.sort_by { |k,v| v.count }.reverse.map{|a| a[0]}

但是这作为group_by函数非常慢。我应该注意到我正在使用PostgreSQL,这意味着我在互联网上找到的一些解决方案对我没用。

1 个答案:

答案 0 :(得分:0)

假设您只想计算在上个月"" (从"现在"倒数):

SELECT store_id 
FROM   product
WHERE  created_at > now() - interval '1 month'
GROUP  BY store_id 
ORDER  BY count(*) DESC;

我甚至没有包含store表。如果没有任何合格产品,您只能获得store_id而没有商店。这是最快的。
created_at上的索引将起到重要作用。 (created_at, store_id)上的多列索引将进一步优化。更昂贵,更专业,但对于手头的查询更快。在pg 9.2+中你可以得到index-only scans

要包含store表的列以及包含0个合格产品的商店:

SELECT s.*
FROM   store s
LEFT   JOIN (
   SELECT store_id, count(*) AS ct_prod
   FROM   product
   WHERE  created_at > now() - interval '1 month'
   GROUP  BY store_id
  ) p ON s.store_id = p.store_id
ORDER  BY p.ct_prod DESC NULL LAST, s.store_id;

NULLS LAST对于最后没有任何匹配的行进行排序至关重要 我添加了s.store_id作为任意关系,以便为具有相同ct_prod的商店获得一致的排序顺序。