【问题标题】:Display latest messages from messages table, group by user显示消息表中的最新消息,按用户分组
【发布时间】:2014-05-19 00:47:32
【问题描述】:

我正在尝试为用户之间的消息创建一个收件箱。
以下是下表:

Messsages
Id | Message_from | message_to | message
1  | 2            |   1        | Hi
2  | 2            |   1        | How are you
3  | 1            |   3        | Hola
4  | 4            |   1        | Whats up
5  | 1            |   4        | Just Chilling
6  | 5            |   1        | Bonjour

Users
Id | Name
1  | Paul
2  | John
3  | Tim
4  | Rob
5  | Sarah
6  | Jeff

我想显示一个收件箱,显示此人已交流的用户列表以及来自任一用户的 last_message

保罗的收件箱:

Name | user_id | last_message
Sarah| 5       | bonjour
Rob  | 4       | Just Chilling
Tim  | 3       | Hola
John | 2       | How are you 

如何使用 Active Records 做到这一点?

【问题讨论】:

    标签: ruby-on-rails ruby postgresql activerecord ruby-on-rails-4


    【解决方案1】:

    这应该是相当有效的:

    SELECT u.name, sub.*
    FROM  (
       SELECT DISTINCT ON (1)
              m.message_from AS user_id
            , m.message AS last_message
       FROM   users    u
       JOIN   messages m ON m.message_to = u.id
       WHERE  u.name = 'Paul'   -- must be unique
       ORDER  BY 1, m.id DESC
       ) sub
    JOIN  users u ON sub.user_id = u.id;
    

    使用DISTINCT ON 计算子查询sub 中具有最新消息的所有用户。然后加入 表users第二次解析名称。

    DISTINCT ON的详细信息:
    Select first row in each GROUP BY group?

    另外:使用“id”和“name”作为列名并不是一个很有帮助的命名约定。

    【讨论】:

    【解决方案2】:

    这个怎么样:

    @received_messages = current_user.messages_to.order(created_at: :desc).uniq
    

    如果您还想包含来自用户的消息,您可能需要执行一个联合查询或两个查询,然后合并并加入它们。我只是在这里用一些伪代码猜测,但这应该会让你上路。

    received_messages = current_user.messages_to
    sent_messages = current_user.messages_from
    (received_messages + sent_messages).sort_by { |message| message[:created_at] }.reverse
    

    这种类型的逻辑属于模型,而不是控制器,所以也许你可以将它添加到 message 模型中。

    【讨论】:

    • @user3649729 啊哈……这有点棘手……让我考虑一下!
    • @user3649729 因为你使用的是同一张表,你也许可以做一些联合查询,或者两个查询,然后合并和排序结果...
    • 问题是一旦我加入这两个查询。我无法对结果进行排序。再次感谢!
    • @user3649729 我拿出了代码。错了...见我之前的两个 cmets。
    • 所以你可以告诉我如何“做某种类型的联合查询,或两个查询,然后合并和排序结果。”谢谢。
    【解决方案3】:
    scope :ids_of_latest_per_user, -> { pluck('MAX(id)').group(:user_id) }
    scope :latest_per_user,        -> { where(:id => Message.latest_by_user) }
    
    Message.latest_per_user
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 2014-02-16
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多