【问题标题】:Rails: order the results returned from DISTINCT ON * ORDERRails:对 DISTINCT ON * ORDER 返回的结果进行排序
【发布时间】:2020-02-17 14:09:55
【问题描述】:

我有以下 Rails 模型:ChatMessages,其中聊天可以包含许多消息。我有以下 Rails 查询来从用户那里提取他作为收件人的每个聊天的最后一条消息:

def index
  messages = Message.where(recipient_id: id)
                    .select('DISTINCT ON ("chat_id") *')
                    .order(:chat_id, created_at)
end

这向我提供了用户参与的每个聊天的最后一条消息。我现在想按创建消息的时间对该查询的结果进行排序,以便最新消息显示在顶部。但是,如果我添加

sorted = messages.order(created_at: :desc)

它不对第一个查询的结果进行排序,它只是将 order by 附加到第一个查询(我知道这是预期的行为),所以我没有按创建日期获得排序列表。如何对第一个查询的结果进行排序?基本上可以用 Rails 语法模仿以下内容:

SELECT *
FROM (SELECT DISTINCT ON (chat_id) *
      FROM messages
      ORDER BY chat_id, created_at DESC) last_messages
ORDER BY created_at DESC

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    试试这个

    Message.from(
      Message.where(recipient_id: id)
        .select('DISTINCT ON ("chat_id") *')
        .order("chat_id, created_at DESC"), 
        :messages
    ).order(created_at: :desc)
    

    【讨论】:

    • 这很棒。我不知道from 查询选项。非常优雅,正是我想要的。
    【解决方案2】:

    你可以这样做 -

    def index
      messages = Message.where(recipient_id: id)
                    .select('DISTINCT ON ("chat_id") *, created_at')
                    .order(:chat_id, created_at)
                    .sort_by(&:created_at).reverse
    end
    

    【讨论】:

    • 这很好,但这需要一个 sql 查询,然后 Ruby 来处理结果,而其他两个答案只需要一个 sql 查询。
    • 我同意并感谢您的反馈
    【解决方案3】:

    第一个选项是 unscope :ordermessages 然后用你想要的列再次排序。

    sorted = messages.unscope(:order).order(created_at: :desc)
    

    如果您无法取消messages 的范围,另一种选择是将messages 转换为子查询。

    sorted = Message.where(id: messages).order(created_at: :desc)
    

    【讨论】:

    • 我更喜欢第二个选项,因为(对我而言)它更具语义性,但我必须添加 pluck(:id) 才能使其工作:sorted = Message.where(id: messages.pluck(:id)).order(created_at: :desc)。我赞成你的回答,但@PGill 有最优雅的解决方案,所以我给了他支票。
    • 谢谢,完全同意PGill的回答更好
    猜你喜欢
    • 2019-10-05
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多