ВЫБЕРИТЕ МАКС. В GROUP BY, но ОГРАНИЧИВАЙТЕ результаты до 1 в MYSQL

0

У меня есть следующие таблицы:

Задача (id,....)

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

Обратите внимание, что end_at - это метка времени, и у одной задачи есть много TaskPlans. Мне нужно запросить MAX end_at для каждой задачи.

Этот запрос работает отлично, за исключением случаев, когда у вас одинаковая метка времени для разных TaskPlans. В этом случае мне будет возвращено несколько TaskPlans с MAX end_at для той же Задачи.

Я знаю, что это маловероятная ситуация, но все равно я могу ограничить количество результатов для каждого 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';

Это работает, за исключением описанной выше ситуации, как это можно достичь? Также в подзапросе, instad из 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 [1055] [42000]: выражение №1 в списке SELECT не находится в предложении GROUP BY и содержит неагрегированный столбец "TaskPlan.id", который функционально не зависит от столбцов в предложении GROUP BY; это несовместимо с sql_mode = only_full_group_by

Любые объяснения и предложения были бы очень желанными!

Примечание по дубликатному ярлыку: (теперь снова открыта)

Я уже изучил этот вопрос, но он не дает ответа на мою ситуацию, когда в результате есть несколько максимальных значений, и его нужно отфильтровать, чтобы включить только одну строку результата для каждой группы.

  • 2
    Используйте SELECT taskid, MAX(end_at) FROM TaskPlan GROUP BY task_id или SELECT id, MAX(end_at) FROM TaskPlan GROUP BY id вместо SELECT id, MAX(end_at) FROM TaskPlan GROUP BY task_id
Теги:
dbeaver

3 ответа

1
Лучший ответ

Используйте 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';
  • 0
    Спасибо за ваш ответ. Тем не менее, это все еще дает мне эти проблемы. Во-первых, мне сказали, что This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery . Я понимаю, что это может быть связано с моей версией, но вторая также будет иметь мою предыдущую проблему в случае нескольких планов задач с одинаковыми значениями task_id и end_at . :)
  • 1
    @toing_toing. , , Первый должен быть = , а не in .
Показать ещё 1 комментарий
1

Если вы хотите получить список идентификаторов задач с MAX 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 настолько велика, вы можете избежать "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;
  • 0
    Это выглядит прекрасно, если бы я мог получить целые строки соответствующего TaskPlan, а не t.id! или, по крайней мере, если бы я мог получить идентификатор от tp, я мог бы манипулировать им. Спасибо!
  • 1
    Вы можете присоединиться к этому с помощью подзапроса, в котором есть строки TaskPlan с максимальными датами каждой задачи.
Показать ещё 3 комментария
0

Попробуйте этот запрос:

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;
  • 0
    Это дало мне пустые значения end_at в результатах. У меня нет пустых строк в таблице PT.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню