按第二个参数分组

时间:2013-03-31 23:22:14

标签: mysql

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

这是由对话组成的。当它分组并保留一行时,我需要它是最近的sent_date行。

这种结构有可能吗?

感谢。

2 个答案:

答案 0 :(得分: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

这是在计算每条消息的最大发送日期。然后它将它连接到消息表,它会获取最后一条消息。理论上,如果两个消息在同一时间发送,您可以获得重复。我认为这不太可能。

答案 1 :(得分:2)

问题是您只在SELECT列表中的一列进行分组。 MySQL使用GROUP BY子句的扩展,允许排除SELECT列表中的列在group by或aggregate函数中的名称。这可能会导致意外结果。 (见MySQL Extensions to 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