较大查询中的Groupwise最大值

时间:2014-12-26 21:40:43

标签: mysql sql groupwise-maximum

对于使用groupwise最大值的查询真的很困难,任何帮助都会非常感激。如果我不应该使用groupwise最大值,请随时指出。

我有两个表applicationemail,一个应用程序可以有很多电子邮件。我在我的查询中尝试做的是从应用程序获取所有详细信息并加入电子邮件表(我实际上只从电子邮件中获取另一个表的外键,表明该电子邮件是否已被回复) ,根据最大值(时间戳)发送最后一封电子邮件,这就是我尝试使用groupwise最大值的原因。

我已经尝试过了,但它似乎重复了每一行:

SELECT  `application` . * ,  `email1`.`student_email_id` AS  `email_student_email_id` 
FROM  `application` 
LEFT JOIN (
  SELECT MAX( tstamp ) AS tstamp, id, student_email_id, application_id
  FROM email
  GROUP BY id, student_email_id, application_id
) AS email1 ON  `email1`.`application_id` =  `application`.`id` 
WHERE  `application`.`status` =  'returned'

这一开始似乎起作用,但现在引起了问题,我确信它的代码非常草率:

select `application`.*, `email1`.`student_email_id` as `email_student_email_id`
from `application` 
left join (
  select student_email_id, max(tstamp) as tstamp, application_id
  from email 
  group by application_id, tstamp
  order by tstamp desc
  limit 1) as email1 on `email1`.`application_id` = `application`.`id` 
where `application`.`status` = 'returned'

如果您需要查看更多代码,请高度赞赏任何指导!感谢。

如果我的数据库设置需要进一步清晰,应该发生什么(遗漏了不重要的部分):

Application Table
+----+----------+
| id |  status  |
+----+----------+
|  1 | returned |
+----+----------+

Email Table
+----+------------+----------------+------------------+
| id |   tstamp   | application_id | student_email_id |
+----+------------+----------------+------------------+
|  1 | 2014-12-26 |              1 | NULL             |
|  2 | 2014-12-27 |              1 | 3                |
+----+------------+----------------+------------------+

查询应显示以下内容:

+----+----------+------------------------+
| id |  status  | email_student_email_id |
+----+----------+------------------------+
|  1 | returned |                      3 |
+----+----------+------------------------+

上面的第一个解决方案显示了所有内容的重复(可能是我几乎在那里),第二个解决方案显示了连接表列的null,尽管我确信它在一个阶段或至少在隔离中工作!

1 个答案:

答案 0 :(得分:4)

您正在Email表格中查找每个不同application_id的最新行。

你得到的子查询并不是很正确。这就是你如何做到的。

SELECT s.application_id, e.student_email_id
  FROM email e
  JOIN (
         SELECT MAX(tstamp) tstamp, application_id
           FROM email
          GROUP BY application_id
       ) s ON e.application_id = s.application_id AND e.tstamp = s.tstamp

还有另一种方法可以做到这一点,这可能会更有效率。如果id列是自动增量列,它将起作用。

SELECT s.application_id, e.student_email_id
  FROM email e
  JOIN (
         SELECT MAX(id) id
           FROM email
          GROUP BY application_id
       ) s ON e.id = s.id

前面这些子查询中的任何一个都会为每个application_id获取最新的student_email_id。第二个使用JOIN仅为每个application_id提取最高的id号,并使用该id查找最新的student_email_id。

你的子查询是这样的。它没有得到你所希望的。

 SELECT MAX( tstamp ) AS tstamp, id, student_email_id, application_id /*wrong*/
   FROM email
  GROUP BY id, student_email_id, application_id 

您按ID分组。这意味着您将获得所有细节行。这不是你想要的。即便如此

 SELECT MAX( tstamp ) AS tstamp, student_email_id, application_id  /*wrong*/
   FROM email
  GROUP BY student_email_id, application_id 

将为每个application_id值提供多条记录。

所以你需要的查询是:

SELECT  application.* ,  email1.student_email_id AS  email_student_email_id 
  FROM  application 
  LEFT JOIN (
              SELECT s.application_id, e.student_email_id
                FROM email e  
                JOIN (
                       SELECT MAX(id) id
                         FROM email
                        GROUP BY application_id
                     ) s ON e.id = s.id
           ) AS email1 ON  email1.application_id =  application.id 
 WHERE application.status =  'returned'

当您设计这样的查询时,从内到外进行测试是明智的,从最里面的子查询开始。