-1
SELECT c.user1, c.user2, a.username AS author_name, SUBSTRING(m.content,1,20) as content, m.viewed, m.sent_date, m.author, c1.username AS username1, c2.username AS username2  
FROM conversation c
INNER JOIN message m ON m.conversationid = c.conversationid
INNER JOIN user c1 ON c1.userid = c.user1
INNER JOIN user c2 oN c2.userid = c.user2
INNER JOIN user a ON a.userid = m.author
WHERE (c.user1 = 33 OR c.user2 = 34)
GROUP BY c.conversationid ORDER BY m.sent_date DESC

这按对话 ID 分组。当它分组并保留一行时,我需要它是最近发送日期的行。

这种结构有可能吗?

谢谢。

4

2 回答 2

2

执行此操作的安全方法是添加一个子查询来计算每个对话的最近发送日期:

SELECT c.user1, c.user2, a.username AS author_name, SUBSTRING(m.content,1,20) as content, m.viewed, m.sent_date, m.author, c1.username AS username1, c2.username AS username2  
FROM conversation c
INNER JOIN message m ON m.conversationid = c.conversationid
inner join (select conversationid, max(sent_date) as maxsentdate from message group by conversationid) mc on m.conversationid = mc.conversationid and m.sent_date = mc.maxsentdate
INNER JOIN user c1 ON c1.userid = c.user1
INNER JOIN user c2 oN c2.userid = c.user2
INNER JOIN user a ON a.userid = m.author
WHERE (c.user1 = 33 OR c.user2 = 34)
GROUP BY c.conversationid ORDER BY m.sent_date DESC

这样做是计算每条消息的最大发送日期。然后它将它加入到消息表中,得到最后一条消息。如果两条消息同时发送,理论上你可以得到重复消息。我认为这不太可能。

于 2013-03-31T23:24:53.157 回答
2

问题是您仅按SELECT列表中的一列进行分组。MySQL 使用对子句的扩展,该GROUP BY子句允许 SELECT 列表中的列被排除在 group by 或聚合函数中。这可能会导致意想不到的结果。(参见MySQL 对 GROUP BY 的扩展

来自 MySQL 文档:

MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。...您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要在每个未在 GROUP BY 中命名的非聚合列中的所有值对于每个组都相同时很有用。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。在选择了值之后对结果集进行排序,并且 ORDER BY 不会影响服务器选择的值。

理想情况下,您将使用子查询来获取结果。此子查询将获取每个对话的最大 sent_Date,然后您将其加入您的消息表以返回所需的剩余列:

SELECT c.user1, 
  c.user2, 
  a.username AS author_name, 
  SUBSTRING(m.content,1,20) as content, 
  m.viewed, 
  m.sent_date, 
  m.author, 
  c1.username AS username1, 
  c2.username AS username2  
FROM conversation c
INNER JOIN message m
  ON m.conversationid = c.conversationid
INNER JOIN
(
  select max(sent_date) sent_date, conversationid
  from message
  group by conversationid
) m1
  ON m1.conversationid = c.conversationid
  AND m.sent_date = m1.sent_date
INNER JOIN user c1 
  ON c1.userid = c.user1
INNER JOIN user c2 
  ON c2.userid = c.user2
INNER JOIN user a 
  ON a.userid = m.author
WHERE (c.user1 = 33 OR c.user2 = 34)
ORDER BY m.sent_date DESC
于 2013-03-31T23:27:36.347 回答