Мисля, че това го прави.
select
t_task.task_id,
t_task.task_name,
latest_action.act_date,
IFNULL(t_act_d.act_name, 'Pending') as act_name
from
t_task
left outer join (
select
@row_num := IF(@prev_value=concat_ws('', t_act.task_id),@row_num+1, 1) as row_number,
t_act.task_id,
t_act.act_id,
t_act.act_date,
@prev_value := concat_ws('', t_act.task_id) as z
from
t_act,
(select @row_num := 1) x,
(select @prev_value := '') y
order by
t_act.task_id,
t_act.act_date desc
) as latest_action on
t_task.task_id = latest_action.task_id
left outer join t_act_d on
latest_action.act_id = t_act_d.act_id
where
latest_action.row_number = 1 or
latest_action.row_number is null
order by
case when latest_action.act_date is null then '9999-01-01' else latest_action.act_date end
Резултатите от предоставените от вас данни са:
+---------+-----------------+------------+-----------+
| task_id | task_name | act_date | act_name |
+---------+-----------------+------------+-----------+
| A1 | PC Proc | 2017-07-17 | Execution |
| A2 | Printer Proc | 2017-07-21 | Surveying |
| A3 | Stationery Proc | NULL | Pending |
+---------+-----------------+------------+-----------+
По-запознат съм с T-SQL, където бих използвал прозоречната функция row_number(). Идеята е полето row_number да показва класиране на всеки ред по отношение на това дали е най-скорошното (стойност 1), второто най-скорошно (стойност 2) и т.н. действие за всяка задача. Най-скорошното действие за всяка задача завършва с row_number 1, така че можете да ги извадите, като филтрирате по row_number =1 от това latest_action
подзаявка.
Тъй като latest_action
подзаявката се изпълнява веднъж като цяло, а не веднъж на ред, това не е голям удар в производителността. За съжаление, не мога да обещая, че цялата настройка на променливата/увеличаването не е голям удар в производителността, това е първият път, когато използвам тази логика в MySQL, не знам колко е ефективна.
Логиката за това как да се възпроизведе функционалността row_number() на T-SQL идва от тук: ROW_NUMBER() в MySQL