我正在尝试制作聊天系统。它有2个表(聊天,用户),具有以下模式。聊天表
我想根据任意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。
答案 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 JOIN
或User
与Chat
共享值的任何一个FromUserID
和ToUserID
之间执行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