获取每个朋友的所有最后消息 - SQL

时间:2018-05-15 18:19:09

标签: mysql sql

我正在尝试从每个朋友那里选择最后一条消息,就像所有其他聊天应用程序一样。这是我到目前为止所拥有的。

SELECT m.message, 
                   m.message_read,
                   m.message_date,
                   CASE WHEN m.sender = 4
                        THEN m.receiver
                        ELSE m.sender
                   END as friend_id,
                   CASE WHEN m.sender = 4
                        THEN p2.nickname
                        ELSE p1.nickname
                   END as name,
                   CASE WHEN m.sender = 4
                        THEN p2.image
                        ELSE p1.image
                   END as image
            FROM message as m
            JOIN profile as p1
              ON m.sender = p1.user_id    -- sender
            JOIN profile as p2 
              ON m.receiver = p2.user_id  -- receiver
            WHERE 4 IN (m.sender, m.receiver)

上面的select语句获取

+-----------+--------------+---------------------+-----------+-------+-------+
| message   | message_read | message_date        | friend_id | name  | image |
+-----------+--------------+---------------------+-----------+-------+-------+
| Hey Buddy |            1 | 2018-05-10 11:58:39 |         1 | JUAN  | NULL  |
| SUP MATE  |            1 | 2018-05-15 11:04:24 |         1 | JUAN  | NULL  |
| nooo      |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| lulz      |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| shut up   |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| heha      |            1 | 2018-05-15 10:36:11 |         2 | user3 | NULL  |
+-----------+--------------+---------------------+-----------+-------+-------+

我专门使用消息表中的message_date变量对这些消息进行排序。

消息表:

+----+--------+----------+-----------+--------------+-----------------+---------------------+
| id | sender | receiver | message   | message_read | message_visible | message_date        |
+----+--------+----------+-----------+--------------+-----------------+---------------------+
|  1 |      4 |        2 | lulz      |            1 |               2 | 2018-05-15 10:24:36 |
|  2 |      1 |        4 | Hey Buddy |            1 |            NULL | 2018-05-10 11:58:39 |
|  3 |      2 |        4 | nooo      |            1 |               2 | 2018-05-15 10:24:36 |
|  4 |      4 |        2 | shut up   |            1 |               2 | 2018-05-15 10:24:36 |
|  5 |      4 |        2 | heha      |            1 |            NULL | 2018-05-15 10:36:11 |
|  6 |      1 |        4 | SUP MATE  |            1 |            NULL | 2018-05-15 11:04:24 |
+----+--------+----------+-----------+--------------+-----------------+---------------------+

我想得到

的结果
+-----------+--------------+---------------------+-----------+-------+-------+
| message   | message_read | message_date        | friend_id | name  | image |
+-----------+--------------+---------------------+-----------+-------+-------+
| SUP MATE  |            1 | 2018-05-15 11:04:24 |         1 | JUAN  | NULL  |
| heha      |            1 | 2018-05-15 10:36:11 |         2 | user3 | NULL  |
+-----------+--------------+---------------------+-----------+-------+-------+

请帮我解决这个问题。任何评论都会有所帮助!这也应该考虑相同的message_date。例如如果有两条消息具有完全相同的日期/时间,则只应选择其中一条消息。我正在考虑消息表的id来选择其中的哪一个。

2 个答案:

答案 0 :(得分:1)

有点像

select m.*
from 
message m
left join message m1 on (
  (
    (m.sender = m1.sender and m.receiver = m1.receiver)
                          or
    (m.sender = m1.receiver and m.receiver = m1.sender )
  )
   and case when m.message_date = m1.message_date
            then m.id < m1.id
            else m.message_date < m1.message_date
       end
)
where m1.id is null
and 4 in(m.sender, m.receiver)

我添加了case表达式来检查相同日期时间是否有多条消息,然后根据id选择最新消息,我假设id设置为自动递增。

Demo

答案 1 :(得分:-1)

使用row_number和partition by。

select * from
(SELECT m.message, 
               m.message_read,
               m.message_date,
               CASE WHEN m.sender = 4
                    THEN m.receiver
                    ELSE m.sender
               END as friend_id,
               CASE WHEN m.sender = 4
                    THEN p2.nickname
                    ELSE p1.nickname
               END as name,
               CASE WHEN m.sender = 4
                    THEN p2.image
                    ELSE p1.image
               END as image,
       ROW_NUMBER() OVER (PARTITION BY friend_id ORDER BY m.message_date DESC) AS rn               
        FROM message as m
        JOIN profile as p1
          ON m.sender = p1.user_id    -- sender
        JOIN profile as p2 
          ON m.receiver = p2.user_id  -- receiver
        WHERE 4 IN (m.sender, m.receiver)
) t
where rn=1