我的数据库里有张桌子:
sentBy
和sentTo
是FK到User
表。
在这个表中,我在用户之间有消息:
sentBy | sentTo | dateSent | body
-------+----------+------------------+-----------------
1 | 2 | 11/21/2010 10:00 | Hey!
-------+----------+------------------+-----------------
2 | 1 | 11/21/2010 10:50 | Hi!
-------+----------+------------------+-----------------
1 | 2 | 11/21/2010 10:51 | msg body 1
-------+----------+------------------+-----------------
2 | 1 | 11/21/2010 11:05 | msg body 2
-------+----------+------------------+-----------------
1 | 3 | 11/21/2010 11:51 | msg body 3
-------+----------+------------------+-----------------
3 | 1 | 11/21/2010 12:05 | msg body 4
-------+----------+------------------+-----------------
1 | 3 | 11/21/2010 12:16 | msg body 5
-------+----------+------------------+-----------------
4 | 1 | 11/21/2010 12:25 | msg body 6
-------+----------+------------------+-----------------
我需要知道与用户1交谈过的用户以及与用户1交谈过的用户。在这种情况下,用户2、3和4(请注意,用户4已经向用户1发送了消息,但用户1尚未发送任何消息)。
第二个问题是:,我怎样才能得到每个用户的最后一条消息?,我要问的是如何将最新的消息发送给用户。
例如,如果我询问用户1,用户2的最新消息是: msg 2,而用户3的最新消息是msg 5。
如何在一个SELECT语句中获得该信息?或可能需要两个SELECT。
我试着做一些像WhatsApp这样的事情。这里有一个聊天屏幕,上面有我与之交谈过的用户列表(我的第一个问题),以及与他们交谈的最后一条信息(我的第二个问题)。
也许我可以创建另一个名为Conversation
的表,将sentBy
和sentTo
移到该表中,并将发送给它的日期作为最后一条消息,但我认为这不是一个好的设计。
我的两个问题的结果是:
sentBy | sentTo | dateSent | body
-------+----------+------------------+-----------------
2 | 1 | 11/21/2010 11:05 | msg body 2
-------+----------+------------------+-----------------
1 | 3 | 11/21/2010 12:16 | msg body 5
-------+----------+------------------+-----------------
4 | 1 | 11/21/2010 12:25 | msg body 6
-------+----------+------------------+-----------------
发布于 2013-10-29 08:04:39
以下查询将为用户1提供预期的结果:
select m.* from messages m
join (
select auser,withuser,max(datesent) datesent from (
select sentby as auser,sentto as withuser,datesent from messages
union
select sentto as auser,sentby as withuser,datesent from messages
) as ud
group by auser,withuser
) maxud
on (m.datesent=maxud.datesent and maxud.auser in (m.sentBy,m.sentTo))
where auser=1
不用说,您可以更改where
子句中的条件,以便为任何用户获得类似的结果。
但是,我的方法是创建一个视图,然后从视图中进行选择,如下所示:
create view conversation_stuff as
select m.sentBy,m.sentTo,m.dateSent,m.body,maxud.auser,maxud.withuser
from messages m
join (
select auser,withuser,max(datesent) datesent from (
select sentby as auser,sentto as withuser,datesent from messages
union
select sentto as auser,sentby as withuser,datesent from messages
) as ud
group by auser,withuser
) maxud
on (m.datesent=maxud.datesent and maxud.auser in (m.sentBy,m.sentTo))
select sentBy,sentTo,dateSent,body from conversation_stuff where auser=1;
我想这对其他用途也是有用的。
编辑:将user
改为auser
everywhere,以便sqlserver停止抱怨,并避免[]
的.
发布于 2013-10-29 07:16:48
选择在dateSent上筛选的最大sentBy并按sentTo分组,然后将此结果加入到原始表中。
编辑:我看到问题了。您想要用户发送的和收到的消息的最大消息吗?
SELECT
Messages.*
FROM
Messages
INNER JOIN
(
SELECT
CombinedKey,
MAX(dateSent) AS dateSent
FROM
(
SELECT
CombinedKey = CASE WHEN sentBy > sentTo
THEN CAST(sentBy AS nvarchar(10)) + '_'
+ CAST(sentTo AS nvarchar(10))
ELSE CAST(sentTo AS nvarchar(10)) + '_'
+ CAST(sentBy AS nvarchar(10))
END,
MAX(dateSent) AS dateSent
FROM
Messages
WHERE
sentBy = @user
OR sentTo = @user
GROUP BY
sentBy,
sentTo
) AS MaxMessagesBoth
GROUP BY
CombinedKey
) AS MaxMessages
ON MaxMessages.CombinedKey = CASE WHEN sentBy > sentTo
THEN CAST(sentBy AS nvarchar(10)) + '_'
+ CAST(sentTo AS nvarchar(10))
ELSE CAST(sentTo AS nvarchar(10)) + '_'
+ CAST(sentBy AS nvarchar(10))
END
AND MaxMessages.dateSent = Messages.dateSent
https://stackoverflow.com/questions/19651811
复制相似问题