2016-08-30 25 views
-1

我有一张桌面充满了用户之间的消息,并且我想从每个用户的userFrom不是我的用户(4)中选择最后一条消息,但是如果最后一条消息到另一个用户(userTo)是我的用户(4)和另一个用户之间的最后一条消息,那么这应该是返回记录中msg的值。如何使用MySQL GROUP BY选择唯一值

TABLE消息

id|userFrom|userTo|msg 
------------------------- 
1 | 4  | 9 |msg 1  
2 | 9  | 4 |msg 2  
3 | 4  | 63 |msg 1  
4 | 63 | 4 |msg 2  
5 | 4  | 9 |msg 3  
6 | 9  | 4 |msg 4  
7 | 9  | 4 |msg 5 
8 | 63 | 4 |msg 3 

我的最终目标是使用数据显示,从独特的用户的邮件列表,其中每行是不同的用户,它显示了我的用户和用户之间的最后一条消息(视觉参考我试图创造一些像Facebook消息)

我怎么会喜欢上表数据返回

id|userFrom|msg 
------------------------- 
7 | 9  |msg 5  
8 | 63 |msg 3 

我需要的用户从独特,所以我可以扩展查询做额外的连接,从用户表中获取实际的varchar用户名,其中userFrom是一些用户,但不是我自己的用户。

+0

id 8从哪里来? – kbball

+0

您可以使用子查询为用户选择最后一条消息。 – mm759

+0

@kbball我忘了包括它..我编辑,因为你已经查看包括第8行的数据。 –

回答

1

这里有一个选项与leastgreatest

select id, userfrom, userto, msg 
from messages m join (
    select max(id) maxid 
    from messages 
    group by least(userfrom, userto), greatest(userfrom, userto) 
) t on m.id = t.maxid 

顺便说一句 - 我假设你预期的结果是不正确的。您的示例数据中没有id = 8

+0

但是,您的解决方案能够正常工作,因为我在查询中加入了额外的表格,因为他们并没有真正涉及到这个问题,但是为了透明,我需要在userFrom/userTo上加入一个用户表格在返回的数据如此喜欢加入用户你u.id = messages.userFrom –

+0

@WilliamWorley - 不知道你的评论意味着什么 - 你可以很容易'加入'更多的表到这个结果... – sgeddes

+0

如果我不' t知道我需要加入的用户是,因为我不想在php中过滤结果一旦数据从mysql返回 –

-1

您必须阅读where和having子句之间的区别。

首先,通过WHERE子句(其中userFrom!= 4) 通过 然后使用该组最后筛选由HAVING子句发送给您的邮件(有用户至= 4)

+0

尝试了SELECT * FROM messages其中userFrom!= 4 GROUP BY userFrom,userTo拥有userTo = 4,但是这并没有返回正确的结果,因为它只是重新生成了我不是userFrom的行,并带有错误的msg –

+0

它就像在做有人的功课!您必须使用GROUP BY userFrom,并且在SELECT中它应该是userFrom,max(ID)。一旦获得该ID,再进行一次选择查询即可获取该消息。 –

1

尝试筛选记录这一个:

SELECT messages.id, messages.userFrom, messages.msg 
FROM messages INNER JOIN 
(SELECT userFrom, max(id) AS mxid 
FROM messages 
GROUP BY userFrom) sub 
ON messages.id = sub.mxid 
WHERE messages.UserFrom <> 4 
+0

这只返回一条记录,我需要每个不同用户的所有记录作为userFrom,并且msg是来自该用户或我的用户的最后一条消息 –

+0

我必须对问题的要求感到困惑。我以为你只想要“来自每个用户的最后一条消息”。 – kbball

+0

查询是否不为每个用户返回一行?问题中的示例结果还包含每个用户一行。 – mm759

0

我认为这是你在找什么

CREATE TABLE [dbo].[UserMessage](
    [id] [int] NOT NULL, 
    [userFrom] [int] NOT NULL, 
    [userTo] [int] NOT NULL, 
    [msg] [varchar](50) NOT NULL 
) ON [PRIMARY] 

insert into UserMessage values(1,4,9,'msg 1') 
insert into UserMessage values(2,9,4,'msg 2') 
insert into UserMessage values(3,4,63,'msg 1') 
insert into UserMessage values(4,63,4,'msg 2') 
insert into UserMessage values(5,4,9,'msg 3') 
insert into UserMessage values(6,9,4,'msg 4') 
insert into UserMessage values(7,9,4,'msg 5') 
insert into UserMessage values(8,63,4,'msg 3') 

SELECT lastMesageFrom.*, um.msg 
FROM 
(
select max(id) as id,UserFrom from UserMessage 
where UserTo = 4 
Group by UserFrom 
)as lastMesageFrom 
Left Outer join UserMessage um on um.id = lastMesageFrom.id 

enter image description here

编辑:通过MySQL验证:http://sqlfiddle.com/#!9/1045b/1

+0

这排除了我的用户(4)可能向其他用户发送消息的任何消息,但该用户从未回复过,意味着我可以使用id = 9,userFrom = 4,userTo = 20,msg = msg 1,这个结果应该像9,20,msg 1 –

+0

那样重新编译请看你的查询失败的地方,因为userFrom是用户9两次,它不应该是,它应该是userFrom = 9,msg =“msgg 6“http://sqlfiddle.com/#!9/deb4fe –

+0

实际上,从用户到用户都应该使用一个密钥进行配对以进行聚合,以获得预期的结果。这里是我用来产生pair key的简单逻辑,但这不够强大,应该用更好的逻辑进行优化。但它仍然有效。 选中此的Filder http://sqlfiddle.com/#!9/ccc21f/1 实际的查询是 SELECT消息。*从 邮件内加入 ( SELECT MAX(ID)为maxid, userfrom + userto作为 来自消息 分组by )t on t.maxid = messages.id –