【问题标题】:Groupwise maximum in larger query较大查询中的分组最大值
【发布时间】:2015-02-24 01:38:28
【问题描述】:

对于使用分组最大值的查询真的很苦恼,任何帮助将不胜感激。如果我不应该使用分组最大值,请随时指出。

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

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

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,尽管我确信它确实在一个阶段或至少单独工作!

【问题讨论】:

    标签: mysql sql groupwise-maximum


    【解决方案1】:

    您正在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'
    

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

    【讨论】:

    • 非常感谢,这确实是一个非常巨大的帮助。另外,我还要进一步感谢您提供的详细解释以及使用自动递增主键的替代答案。
    • 感谢您的编辑,@haakym。我更正了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2023-02-05
    相关资源
    最近更新 更多