Reputation: 186562
The query below seems to LIMIT all the results when it's being LEFT JOINed, so the total in the subquery is just 1. How can I make it LIMIT so that I get a 1:1
match between projects
rows and the last date stored in projects_hours_archive
which stores records of projects.projected_hours
that are collected on a cron job once per week?
projected_hours_archive
has columns: id
, project_id
, hours
and datetime
.
SELECT
GROUP_CONCAT( projected_hours_last.date, '|', projected_hours_last.number ) AS 'projected_last_info'
FROM
projects
LEFT JOIN (
SELECT *
FROM
projected_hours_archive
ORDER BY date DESC
LIMIT 1
) AS projected_hours_last ON ( projected_hours_last.project_id = projects.id )
WHERE projected_hours > 0
GROUP BY projects.id
I tried to adopt using MySQL Limit LEFT JOIN Subquery after joining but wasn't successful. If I remove the LIMIT
in the subquery I get too many results.
Upvotes: 5
Views: 6387
Reputation: 4146
I had the same question.
I suppose your field projects.project_id
is unique (so there are no duplicates in that table). Otherwise, you can use DISTINCT(projects.project_id)
or GROUP BY projects.project_id
as you've used before.
Solution #1 (using GROUP BY while joining):
SELECT a1.project_id,
GROUP_CONCAT(a2.date, '|', a2.number ) AS 'projected_last_info'
FROM projects a1
LEFT JOIN (
SELECT b1.project_id, b1.date, b1.number
FROM projected_hours_archive b1
ORDER BY b1.date DESC
GROUP BY b1.project_id
) a2 ON a2.project_id = a1.project_id
WHERE a1.projected_hours > 0
Solution #2 (using LIMIT directly in subquery in SELECT statement):
SELECT a1.project_id,
(SELECT GROUP_CONCAT(a2.date, '|', a2.number )
FROM projected_hours_archive b1
WHERE b1.project_id = a1.project_id
ORDER BY b1.date DESC
) AS 'projected_last_info'
FROM projects a1
WHERE a1.projected_hours > 0
Upvotes: 1
Reputation: 13425
use group by
in the sub query and get maximum date per project.
EDIT: as per the OP comment, adding second max date.
The trick from this mysql how to get 2nd highest value with group by and in a left join is used.
SELECT
GROUP_CONCAT( projected_hours_last.secondMaxDate, '|', projected_hours_last.number ) AS 'projected_last_info'
FROM
projects
LEFT JOIN (
SELECT project_id, max(date) as maxDate,
substring_index(substring_index(group_concat(date order by date desc), ',', 2), ',', -1
) as secondMaxDate
FROM
projected_hours_archive
group by project_id
) AS projected_hours_last ON ( projected_hours_last.project_id = projects.id )
WHERE projected_hours > 0
GROUP BY projects.id
Upvotes: 4