【问题标题】:Sort by frequency of rows in associated table按关联表中的行频率排序
【发布时间】:2014-12-22 16:10:50
【问题描述】:

我有 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,这意味着我在互联网上找到的一些解决方案对我不起作用。

【问题讨论】:

  • 上个月创建的?商店?产品?只计算上个月创建的产品?与往常一样,表定义和您的 Postgres 版本会有所帮助。
  • 上个月创建的产品。我的 Postgres 版本是 9.2.4。

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


【解决方案1】:

假设您只想计算“上个月”创建的产品(从“现在”开始倒数):

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 的商店获得一致的排序顺序。

【讨论】:

    猜你喜欢
    • 2014-11-07
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 2014-06-19
    相关资源
    最近更新 更多