One canonical way to do this is to join to a subquery which finds the latest log_id
value for each group as you have defined it:
SELECT j1.*
FROM job_monitor_log j1
INNER JOIN
(
SELECT job_id, run_id, start_hour, end_hour, MAX(log_id) AS max_log_id
FROM job_monitor_log
GROUP BY job_id, run_id, start_hour, end_hour
) j2
ON j1.job_id = j2.job_id AND
j1.run_id = j2.run_id AND
j1.start_hour = j2.start_hour AND
j1.end_hour = j2.end_hour AND
j1.log_id = j2.max_log_id;
If you can use MySQL 8+ or later, then you may use analytic functions here:
SELECT log_id, job_id, run_id, run_Date, start_hour, end_hour, job_status
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY job_id, run_id, start_hour, end_hour
ORDER BY log_id DESC) rn
FROM job_monitor_log
) t
WHERE rn = 1;
If there could be two or more records per group which are tied regarding having the max log_id
value, then you may replace ROW_NUMBER
with RANK
or DENSE_RANK
to include all such ties.
To cover all bases, we could also use a correlated subquery approach, which is along the lines of what you were originally trying to do:
SELECT log_id, job_id, run_id, run_Date, start_hour, end_hour, job_status
FROM job_monitor_log j1
WHERE log_id = (SELECT MAX(t2.log_id)
FROM job_monitor_log j2
WHERE j1.job_id = j2.job_id AND
j1.run_id = j2.run_id AND
j1.start_hour = j2.start_hour AND
j1.end_hour = j2.end_hour);
This would include all ties for the maximum log_id
value per group. But, this is probably the least performant approach of the three queries given. Sometimes though, when using things like ORM frameworks, we might have the need to express the query as shown above.