SELECT GROUP BY 中的 MAX 但 LIMIT 结果在 MYSQL 中为 1

SELECT MAX in GROUP BY but LIMIT results to 1 in MYSQL

我有以下表格:

Task (id,....)

TaskPlan (id, task_id,.......,end_at)

注意end_at是一个时间戳,一个Task有很多TaskPlans。我需要为每个任务查询 MAX end_at

此查询工作正常,除非您对不同的 TaskPlans 具有完全相同的时间戳。在那种情况下,我将返回多个 TaskPlans,其中 MAX end_at 用于同一 Task.

我知道这种情况不太可能发生,但无论如何我可以将每个 task_id 的结果数量限制为 1 个吗?

我当前的代码是:

SELECT * FROM Task AS t
INNER JOIN (
SELECT * FROM TaskPlan WHERE end_at in (SELECT MAX(end_at) FROM TaskPlan GROUP BY task_id )
) AS pt 
ON pt.task_id = t.id
WHERE status = 'plan';

这个可以,除了上面的情况,怎么实现呢? 同样在 SELECT MAX(end_at) FROM TaskPlan GROUP BY task_id 的子查询中,是否可以做这样的事情,这样我就可以将 TaskPlan.id 用于 where in 子句?

SELECT id, MAX(end_at) FROM TaskPlan GROUP BY task_id

当我尝试时,出现以下错误:

SQL Error [1055] [42000]: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'TaskPlan.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

非常欢迎任何解释和建议!

重复标签注意事项: (现已重新开放)

我已经研究过 this question,但它没有为我的情况提供答案,即结果中有多个最大值,需要过滤掉以每组只包含一个结果行。

试试这个查询:

select t.ID , tp1.end_at
from TASK t
left join TASKPLAN tp1 on t.ID = tp1.id 
left join TASKPLAN tp2 on t.ID = tp2.id and tp1.end_at < tp2.end_at
where tp2.end_at is null;

使用 id 而不是时间戳:

SELECT *
FROM Task AS t INNER JOIN
     (SELECT tp.*
      FROM TaskPlan tp
      WHERE tp.id = (SELECT tp2.id FROM TaskPlan tp2 WHERE tp2.task_id = tp.task_id ORDER BY tp2.end_at DESC LIMIT 1)
     ) tp 
     ON tp.task_id = t.id
WHERE status = 'plan';

或对元组使用 in

SELECT *
FROM Task AS t INNER JOIN
     (SELECT tp.*
      FROM TaskPlan tp
      WHERE (tp.task_id, tp.end_at) in (SELECT tp2.task_id, MAX(tp2.end_at)
                                        FROM TaskPlan tp2 
                                        GROUP BY tp2.task_id
                                       )
     ) tp 
     ON tp.task_id = t.id
WHERE status = 'plan';

如果您想获取每个任务 ID 最大 end_at 的列表,运行 下面的查询:

SELECT t.id, MAX(tp.end_at) FROM Task t JOIN TaskPlan tp on t.id = tp.task_id GROUP BY t.id;

编辑:

现在,我知道你到底要做什么了。 如果 TaskPlan table 太大,可以避免 'GROUP BY' 和 运行 下面的查询非常高效:

SET @first_row := 0;
SET @task_id := 0;

SELECT * FROM Task t JOIN (
   SELECT tp.*
    , IF(@task_id = tp.`task_id`, @first_row := 0, @first_row := 1) AS temp
    , @first_row AS latest_record
    , @task_id := tp.`task_id`

    FROM TaskPlan tp ORDER BY task_id, end_at DESC) a  ON t.task_id = a.task_id AND a.latest_record = 1;