按照发送或接收的最新消息的顺序选择人员

时间:2017-05-02 05:26:34

标签: php mysql sql select

我正在尝试制作聊天系统。它有2个表(聊天,用户),具有以下模式。聊天表
User Table Schema

用户表
User Table Schema

我想根据任意2个用户之间的最新消息选择一个人与之聊天的所有用户。
示例:
考虑我有一个名为X的用户并且他/她已经与A,B,C,D聊天。我必须首先从聊天表中找到A,B,C,D(即所有与人X聊天的用户)。然后,对于每个用户A,B,C,D,找到他们从X发送或接收的最新消息的ChatDateTime,并根据它对A,B,C,D进行排序。

聊天表如下所示:

+--------+------------+----------+----------+--------------+
| ChatId | FromUserId | ToUserId | ChatText | ChatDateTime |
+--------+------------+----------+----------+--------------+
| 1      | 2          | 3        | hai      | 12:30        |
| 2      | 3          | 2        | hello    | 12:34        |
| 3      | 3          | 2        | I am X   | 12:38        |
| 4      | 1          | 3        | I am A   | 12:40        |
| 5      | 2          | 3        | I am B   | 12:41        |
| 6      | 4          | 3        | I am C   | 12:42        |
| 7      | 5          | 3        | I am D   | 12:44        |
| 8      | 3          | 4        | Hai 'C'  | 12:50        |
+--------+------------+----------+----------+--------------+

这里UserId是A = 1,B = 2,X = 3,C = 4,D = 5。从表中我们知道X(UserId = 3)已与A,B,C,D(应首先选择)聊天。最新的对话在C和X之间(ChatId-8)。所以第一个结果应该是C.然后是D(ChatId-7),然后是B(ChatId-5),最后是A(ChatId-4)。所以选择的顺序应该是C,D,B,A。

4 个答案:

答案 0 :(得分:2)

请尝试以下方法......

SELECT latestChatDateTimeFinder.UserID AS UserID,
       latestChatDateTimeFinder.UserName AS UserName,
       latestChatDateTime AS latestChatDateTime,
       otherUserID AS otherUserID,
       User.UserName AS otherUserName
FROM ( SELECT User.UserID AS UserID,
              User.UserName AS UserName,
              CASE
                  WHEN User.UserID = Chat.FromUserID THEN
                      Chat.ToUserID
                  ELSE
                      Chat.FromUserID
              END AS otherUserID,
              MAX( ChatDateTime ) AS latestChatDateTime
       FROM User
       JOIN Chat ON User.UserID = Chat.FromUserID
                 OR User.UserID = Chat.ToUserID
       GROUP BY User.UserID,
                otherUserID
     ) AS latestChatDateTimeFinder
JOIN User ON latestChatDateTimeFinder.otherUserID = User.UserID
ORDER BY latestChatDateTimeFinder.UserID,
         otherUserID;

此语句以以下子查询开始...

SELECT User.UserID AS UserID,
       User.UserName AS UserName,
       CASE
           WHEN User.UserID = Chat.FromUserID THEN
               Chat.ToUserID
           ELSE
               Chat.FromUserID
       END AS otherUserID,
       MAX( ChatDateTime ) AS latestChatDateTime
FROM User
JOIN Chat ON User.UserID = Chat.FromUserID
          OR User.UserID = Chat.ToUserID
GROUP BY User.UserID,
         otherUserID

此子查询基于INNER JOINUserChat共享值的任何一个FromUserIDToUserID之间执行UserID。< / p>

然后选择字段。 CASE语句将根据UserID建立的共享值选择其他JOIN

然后,生成的数据集按两个UserID值进行分组,并通过MAX()函数选择与这两个值的组合相对应的最新日期。

这将为我们提供每个用户及其对应用户的列表以及最近通信的日期时间。

然后,此列表将根据现在标识的另一个用户的User值加入主语句中的UserID,以允许该用户的名称附加到数据集中。

然后从数据集中选择字段,给定别名并排序。

如果您有任何问题或意见,请随时发表评论。

附录

要将结果限制为一个User以及与之对应的所有结果,请尝试使用...

SELECT latestChatDateTimeFinder.UserID AS UserID,
       latestChatDateTimeFinder.UserName AS UserName,
       latestChatDateTime AS latestChatDateTime,
       otherUserID AS otherUserID,
       User.UserName AS otherUserName
FROM ( SELECT User.UserID AS UserID,
              User.UserName AS UserName,
              CASE
                  WHEN User.UserID = Chat.FromUserID THEN
                      Chat.ToUserID
                  ELSE
                      Chat.FromUserID
              END AS otherUserID,
              MAX( ChatDateTime ) AS latestChatDateTime
       FROM User
       JOIN Chat ON ( User.UserID = Chat.FromUserID OR
                      User.UserID = Chat.ToUserID )
                AND User.UserID = targetUser
       GROUP BY otherUserID
     ) AS latestChatDateTimeFinder
JOIN User ON latestChatDateTimeFinder.otherUserID = User.UserID
ORDER BY otherUserID;

......或......

SELECT latestChatDateTimeFinder.UserID AS UserID,
       latestChatDateTimeFinder.UserName AS UserName,
       latestChatDateTime AS latestChatDateTime,
       otherUserID AS otherUserID,
       User.UserName AS otherUserName
FROM ( SELECT User.UserID AS UserID,
              User.UserName AS UserName,
              CASE
                  WHEN User.UserID = Chat.FromUserID THEN
                      Chat.ToUserID
                  ELSE
                      Chat.FromUserID
              END AS otherUserID,
              MAX( ChatDateTime ) AS latestChatDateTime
       FROM User
       JOIN Chat ON User.UserID = targetUser
                AND User.UserID = targetUser
       GROUP BY otherUserID
     ) AS latestChatDateTimeFinder
JOIN User ON latestChatDateTimeFinder.otherUserID = User.UserID
ORDER BY otherUserID;

请注意,targetUser(用于引用相关User的值)可以是显式值或变量。

答案 1 :(得分:0)

第一部分 -  所有与人X聊天的用户

第二部分  与此用户相关的所有用户

我已经将这两部分联合起来了

 select u.UserName,c.toUserId  from userTable u inner join chatTable c where UserID IN (select toUserId from chatTable where fromUserId = 'X' order by ChatDateTime desc ) 
UNION ALL
select u.UserName,c.toUserId  from userTable u inner join chatTable c where UserID IN (select fromUserId from chatTable where fromUserId = 'X' order by ChatDateTime desc ) 

答案 2 :(得分:0)

尝试这样的时间

select max(chatdatetime) as chatdatetime,sec_user from
(select chatid,chatdatetime,
  case when fromuserid='X' then touserid
       when touserid='X' then fromuserid 
  end as sec_user
 from chat 
where fromuserid='X' or touserid='X'
) t
 group by sec_user

答案 3 :(得分:0)

另一种选择:

SELECT t.Id, MAX(t.ChatDateTime) FROM
(SELECT FromUserId AS Id, ChatDateTime FROM Chat
WHERE ToUserId = X
UNION
SELECT ToUserId As Id, ChatDateTime FROM Chat
WHERE FromUserId = X) As t
GROUP BY t.Id
ORDER BY t.ChatDateTime DESC