2013-12-20 88 views
1

奇怪的行为,我做了一个简单的表,用于存储信息:MySQL的:使用UNION,MAX和GROUP BY

+----+--------+----------+--------------+------+ 
| id | sender | receiver |  dt  | text | 
+----+--------+----------+--------------+------+ 
| 1 | a  | b  | ..19.26.00.. | msg1 | 
+----+--------+----------+--------------+------+ 
| 2 | c  | b  | ..19.26.02.. | msg2 | 
+----+--------+----------+--------------+------+ 
| 3 | b  | a  | ..19.26.03.. | msg3 | 
+----+--------+----------+--------------+------+ 

我想选择在交谈最近的消息。例如,对于B我想:

+--------------+--------------+------+ 
| conversation | MAX(maxdt) | text | 
+--------------+--------------+------+ 
| ab   | ..19.26.03.. | msg3 | 
+--------------+--------------+------+ 
| cb   | ..19.26.02.. | msg2 | 
+--------------+--------------+------+ 

所以我用这个查询:

SELECT conversation, MAX(maxdt), text FROM 
(SELECT CONCAT(sender, receiver) AS conversation, MAX(dt) AS maxdt, text 
FROM message 
WHERE receiver='b' GROUP BY conversation 
UNION 
SELECT CONCAT(receiver, sender) AS conversation, MAX(dt) AS maxdt, text 
FROM message 
WHERE sender='b' GROUP BY conversation) AS x 
GROUP BY conversation 

但结果是:

+--------------+--------------+------+ 
| conversation | MAX(maxdt) | text | 
+--------------+--------------+------+ 
| ab   | ..19.26.03.. | msg1 | 
+--------------+--------------+------+ 
| cb   | ..19.26.02.. | msg2 | 
+--------------+--------------+------+ 

因此,日期时间值是正确的,但文字来自错误的元组!

有什么建议吗? SQL Fiddle

+0

即其中文本字段在表中列出的顺序; GROUP_CONCAT(text),你应该看到 – Cez

+0

你会想回到那张表来获得适当的'text'值。 –

回答

2

好吧我有一个可能的解决方案,工作SQL小提琴。试试这个:

SELECT CONCAT('b',other) AS conversation, text, dt AS maxdt FROM 
(
    SELECT IF(sender='b',receiver, sender) AS other, dt, text 
    FROM message 
    WHERE (receiver='b' OR sender='b') order by dt desc 
) 
AS TBL group by other 

如果你想让对话字段标准化,你可以CONCAT('b',other)作为对话。

+0

我编辑它来标准化会话变量并使别名更明智 –

+0

在'select'子句中使用'text'和'dt'使用这里描述的MySQL的扩展(http://dev.mysql.com/doc /refman/5.7/en/group-by-extensions.html)。请注意,文档*明确警告不要在组中的所有行的值相同时使用它。它明确指出使用*不确定*值。换句话说,尽管查询可能工作,但显然它使用了数据库中不支持的功能。 –

0
 SELECT CONCAT(sender,receiver) AS conversation,maxdt,text 
    FROM 
     (SELECT max(dt) as maxdt FROM message WHERE sender = 'b' 
      UNION 
      SELECT max(dt) as maxdt FROM message WHERE receiver = 'b')T1, 
      message T2 
    WHERE T1.maxdt = T2.dt 
    AND (T2.receiver = 'b' OR T2.sender = 'b') 

sqlFiddle

+0

这不适用于所有情况:[sqlFiddle](http://www.sqlfiddle.com/#!2/e286c/2) – xonya

+0

我认为是错误的。我以为你想要最新的消息,其中b是发送者UNION,其中b是接收者的最新消息 –