【问题标题】:How to SELECT only the most recent (and multiple) values once?如何只选择最近的(和多个)值一次?
【发布时间】:2015-04-12 04:53:32
【问题描述】:

我正在尝试查找用户 ID 1 与之进行过对话的人(例如,已交换消息)。我只需要每个其他用户的 id 一次,但我想获得按日期(或最高 ID,因为 id 是增量键)排序的结果 id,其中每个用户与用户的最新对话(消息) 1 发生了。用户1 可能是发送消息的人或接收消息的人,在任何情况下都算作“对话”或与其他用户的互动。

这就是我正在做的事情

    SELECT fromId AS userId FROM messaging
      WHERE toId = 1
    UNION
    SELECT toId AS userId FROM messaging
      WHERE fromId = 1

当然,这只会返回每个用户的 id,而不会按照消息发生的顺序返回结果。例如,如果用户与用户 id 5 进行了对话,并且该消息的 id 高于他与用户 6 的对话,则顺序必须为5, 6

有没有办法只用一个查询来做到这一点?

谢谢。

【问题讨论】:

    标签: mysql select union


    【解决方案1】:

    你已经相当接近了,只需要在联合中添加一个额外的字段作为日期,然后按 id 分组,并按最大时间排序。像这样:

    select id, max(message_time)
      from
        (select fromid id, message_time
           from messaging
           where toid = 1
         union
         select toid id, message_time
           from messaging
           where fromid = 1
        ) q
        group by id
        order by max(message_time) desc;
    

    这里有一个小提琴示例:http://sqlfiddle.com/#!9/d248e/2

    根据评论请求进行编辑

    此查询将获取每个对话的最新消息以及消息文本。

    select t1.id, t1.message_time, t1.message
      from
        (select fromid id, message_time, message
           from messaging
           where toid = 1
         union
         select toid id, message_time, message
           from messaging
           where fromid = 1
        ) t1
        left join
        (select fromid id, message_time, message
           from messaging
           where toid = 1
         union
         select toid id, message_time, message
           from messaging
           where fromid = 1
        ) t2
        on t1.id = t2.id and t1.message_time < t2.message_time
        where t2.id is null
        order by t1.message_time desc;
    

    该查询的一般要点与前面的查询相同 - 构建一个派生表,其中只有用户 ID、消息日期,这次还有消息。在用户 ID 上将该派生表左连接到自身(因此重复联合查询),但在消息时间较长的地方也是如此。因为我们要加入,如果没有具有相同用户 ID 但时间戳更大的消息,我们会在结果的后半部分留下空值。这表明我们拥有最新的消息时间以及文本。剩下要做的就是根据这些空值进行过滤,然后进行排序。

    updated fiddle

    【讨论】:

    • 太好了,这行得通!谢谢。我知道这不在最初的问题中,但我想成为另一个问题还不够,我希望这不是一个延伸,但我也可以从每个最后的结果中得到最后的消息吗? (假设有一个“消息”列)。我尝试将消息添加到主查询和括号内的查询,但我认为它返回第一个。简而言之,与每个结果的 MAX 日期相关联的消息。
    • 这更复杂 - 但我会补充一点。
    • @GreasyDonkey 完成。抱歉耽搁了。可能有更好的方法来获得结果 - 但最好的方法是我认为有一个“对话”表,其中列出了对话中的参与者,然后每条消息都用对话 ID 标记。 Skype 就是这样做的。
    • 别担心,效果很好!我仍然无法完全理解 SQL,我不知道为什么我发现它比其他语言更难理解,但你的帮助很棒,我想我明白了。我肯定会检查一下,看起来这将是一种更“灵活”的构建事物的方式。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多