MYSQL在使用GROUP BY时显示不正确的行

MYSQL在使用GROUP BY时显示不正确的行,mysql,select,group-by,max,greatest-n-per-group,Mysql,Select,Group By,Max,Greatest N Per Group,我有两张桌子: article('id', 'ticket_id', 'incoming_time', 'to', 'from', 'message') ticket('id', 'queue_id') 其中,票证代表支持人员和客户之间的一系列电子邮件,而文章则是组成一系列邮件的单独消息 我希望找到一篇文章,它的最高传入时间表示为每个ticket_id的unix时间戳,这是我当前使用的查询: SELECT article.* , MAX(article.incoming_time) as ma

我有两张桌子:

article('id', 'ticket_id', 'incoming_time', 'to', 'from', 'message')
ticket('id', 'queue_id')
其中,票证代表支持人员和客户之间的一系列电子邮件,而文章则是组成一系列邮件的单独消息

我希望找到一篇文章,它的最高传入时间表示为每个ticket_id的unix时间戳,这是我当前使用的查询:

SELECT article.* , MAX(article.incoming_time) as maxtime
FROM ticket, article
WHERE ticket.id = article.ticket_id
AND ticket.queue_id = 1
GROUP BY article.ticket_id
比如说,

:article:
id --- ticket_id --- incoming_time --- to ------- from ------- message --------
11     1             1234567           help@      client@      I need help...   
12     1             1235433           client@    help@        How can we help?
13     1             1240321           help@      client@      Want food!    
...

:ticket:
id --- queue_id
1      1
...
但是结果看起来是具有最小文章id的行,而不是我正在寻找的具有最高传入时间的文章


任何建议都将不胜感激

这是大多数MySQL程序员遇到的典型障碍

SELECT a1.* FROM article a1 
JOIN 
  (SELECT MAX(a2.incoming_time) AS maxtime
   FROM article a2
   JOIN ticket ON (a2.ticketid=ticket.id)
   WHERE ticket.queue_id=1) xx
  ON (a1.incoming_time=xx.maxtime);
您有一个列ticket_id,它是分组依据的参数。此列中的不同值定义了组。 您有一个列incoming_time,它是MAX的参数。此列中每个组中行的最大值作为MAX的值返回。 您有表文章的所有其他列。为这些列返回的值是任意的,而不是来自出现最大值的同一行。 数据库无法推断您想要的值来自出现最大值的同一行

考虑以下情况:

有多行出现相同的最大值。哪一行应该用来显示文章的列。*

您编写了一个同时返回最小值和最大值的查询。这是合法的,但文章*应该显示哪一行

使用聚合函数,如AVG或SUM,其中没有行具有该值。数据库如何猜测要显示的行

SELECT article.* , AVG(article.incoming_time)
FROM ticket, article
WHERE ticket.id = article.ticket_id
AND ticket.queue_id = 1
GROUP BY article.ticket_id
在大多数品牌的数据库中,以及在SQL标准本身中,都不允许编写这样的查询,因为这种查询具有模糊性。不能在选择列表中包含任何不在聚合函数内或GROUP BY子句中命名的列

MySQL更为宽松。它允许您这样做,并让您自己编写查询而不产生歧义。如果确实存在歧义,它将从组中物理上第一个行中选择值,但这取决于存储引擎

值得一提的是,SQLite也有这种行为,但它选择组中的最后一行来解决歧义。想想看,如果SQL标准没有说明要做什么,那就取决于供应商的实现

以下是一个可以为您解决问题的查询:

SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id 
  AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
  AND a2.ticket_id IS NULL;

换句话说,查找没有其他行a2具有相同的票证id和更大的传入时间的行a1。如果没有找到更多的传入时间,左外连接将返回NULL而不是匹配。

非常有效,答案解释得非常清楚-非常感谢!
SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id 
  AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
  AND a2.ticket_id IS NULL;