【问题标题】:How to get the top 5 per enum of a model in rails?如何在rails中获得模型的前5名?
【发布时间】:2020-07-23 18:00:06
【问题描述】:

假设我有一个名为 post 的模型,它有一个名为 post_typeenum 可以是 adminpublicuser

#app/models/post.rb

class Post < ApplicationRecord
 enum post_type: [ :admin, :public, :user ]
end

如何从每个类别中选择 5 个最后创建的帖子?

我想不出除此之外的任何其他解决方案:

PER_GROUP = 5

admin_posts = Post.admin.order(created_at: :desc).limit(PER_GROUP)
user_posts = Post.user.order(created_at: :desc).limit(PER_GROUP)
public_posts = Post.public.order(created_at: :desc).limit(PER_GROUP)

有什么方法可以以所需的方式从单个查询中获取所有行到数据库。

堆栈

RAILS : 6
PostgresSQL: 9.4

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord


    【解决方案1】:

    我不确定如何翻译成 RAILS,但它是直接的 Postgres 查询。您在子选择中使用 row_number 窗口函数,然后在外部选择中仅保留 row_number 小于或等于 5 的行。

    select *
      from (select post_txt
                 , posted_type
                 , row_number() over (partition by posted_type) rn
              from enum_table
           ) pt
     where rn <= 5 
     order by posted_type;
    

    需要注意的一点是枚举的排序。这样做会按照定义的顺序给出结果,而不是“自然顺序”(在这种情况下是字母数字)。见example here

    【讨论】:

    • 谢谢@Belayer,我会试着把它翻译成ActiveRecords
    【解决方案2】:

    感谢@Belayer 我能够想出一个解决方案。

    PER_GROUP = 5
    
    sub_query = Post.select('*', 'row_number() over (partition by "posts"."post_type" ORDER BY posts.created_at DESC ) rn').to_sql
    
    @posts = Post.from("(#{sub_query}) inner_query")
                 .where('inner_query.rn <= ?', PER_GROUP')
                 .order(:post_type, created_at: :desc)
                 .group_by(&:post_type)
    
    

    由于我只加载了几种不同类型的 5 条记录,group_by 对我来说就可以了。

    【讨论】:

    • 看到翻译后的解决方案很有趣。我很高兴我不必构建一个,特别是如果有多个级别的子选择。但是我可以提供帮助。
    猜你喜欢
    • 2016-10-06
    • 1970-01-01
    • 2012-06-04
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 1970-01-01
    • 2014-01-25
    相关资源
    最近更新 更多