列出每个会话的最后一条(N)消息

时间:2014-03-27 12:48:20

标签: mysql sql greatest-n-per-group

我正在创建一个需要与服务器同步的移动应用程序,为了做到这一点,我需要在每个对话中获得最后的(N)消息。 请注意,此查询已生效,但每次会话中都会收到only最后一条消息。

SELECT users.user_id AS user_id,
       users.username,
       users.picture,
       users.last_seen,
       me.message,
       me.created_on
FROM messages me,
     users
WHERE (me.sender_id=1
       OR me.recipient_id=1)
  AND ((me.sender_id=user_id
        AND me.sender_id<>1)
       OR (me.recipient_id=user_id
           AND me.recipient_id<>1))
  AND NOT exists
    (SELECT 1
     FROM messages me2
     WHERE me2.id>me.id
       AND ((me.sender_id=me2.sender_id
             AND me.recipient_id=me2.recipient_id)
            OR (me.sender_id=me2.recipient_id
                AND me.recipient_id=me2.sender_id)))
ORDER BY me.created_on DESC

2 个答案:

答案 0 :(得分:1)

首先,我们获取按用户和日期排序的所有用户的所有消息。我们引入人工变量来编号用户的消息。当用户ID相同时,我们只增加消息号。如果不同则将其重置为0.

因此子查询返回我们

user_id, mess_n
1        0
1        1
1        2
2        0
2        1
2        2
3        0
3        1
3        2

然后在查询中,只留下编号<10(前10)的消息

select *
from (
    select u.*, m.*, 
           @mess_n_for_user:=if(u.user_id!=@curr_user,0,@mess_n_for_user+1) as mess_n,
           @curr_user:=u.user_id
    from  (SELECT @mess_n_for_user:=0, @curr_user:=-1) sess_var,
         users u join messages m on (u.user_id=m.sender_id 
                                  or u.user_id=m.recipient_id)
    order by u.user_id, m.created_on DESC) all_messages_ordered
where all_messages_ordered.mess_n<10

只需将所有过滤条件添加到查询

已更新

来自sqlfiddle

select * from (
select all_messages_ordered.*,
           @mess_n_for_user:=if(u_id!=@curr_user,0,@mess_n_for_user+1) as mess_n,
           @curr_user:=u_id
from (SELECT @mess_n_for_user:=0, @curr_user:=-1) sess_var,
     (
      select u.id as u_id, u.first_name, m.* 
      from  
         accounts u join messages m on (u.id=m.from or u.id=m.to)
                                  and (m.to=1 or m.from=1)
                                  and u.id<>1
    order by u.id, m.date_time DESC) all_messages_ordered) a
where mess_n<3

答案 1 :(得分:0)

您需要递归查询来选择对话。遵循this answer的方法,将recipient_id / sender_id替换为col3 / col1:

select id, recipient_id, @pv:=sender_id as 'recipient_id' from messages
join
(select @pv:=2)tmp
where recipient_id=@pv

我没有测试过这个,但原则应该是正确的。当然,您需要扩展它以完全解决您的问题...但希望这会有所帮助。