Below are my MYSQL tables. I am not able to figure out what a MySQl query looks like that selects only one row from parent for each month (by latest date in a month) and its consequent child rows. So in the given example it should return rows from the child table with IDs 4,5,6,10,11,12
-
1Could you include what you have tried so far? What is the database you are using - MySQL, SQL Server? – zedfoxus Nov 20 '15 at 16:59
-
@zedfoxus I am using mysql, updated the description. – Kaizar Laxmidhar Nov 20 '15 at 17:00
-
Kaizar I cant understand your logic on why `IDs 4,5,6,10,11,12` are the one selected. – Juan Carlos Oropeza Nov 20 '15 at 17:23
-
I also did not understand the logic. – Jorge Campos Nov 20 '15 at 17:30
-
@JuanCarlosOropeza Because IDs 4,5,6 and 10,11,12 belongs to parent ID 2 and 4 respectively which has the latest date for that month. – Kaizar Laxmidhar Nov 20 '15 at 21:30
-
So any of the answer solve your problem or still need help? – Juan Carlos Oropeza Nov 20 '15 at 21:34
-
@JuanCarlosOropeza haven't tested yet but looking at the answers looks any of them will do the job, Personally I would prefer the shortest sql which I think Moon has answered though JNevill's query is more robust. – Kaizar Laxmidhar Nov 20 '15 at 21:47
4 Answers
I think something like the following would do the trick for you:
SELECT Child.id
FROM parent
INNER JOIN Child ON parent.id = child.parent_id
WHERE parent.`date` IN (SELECT max(`date`) FROM parent GROUP BY YEAR(`date`), MONTH(`date`))
The fun part is the WHERE
clause where we only grab parent
table records where the date
is the max(date)
for that particular month/year combination.

- 46,980
- 4
- 38
- 63
Ok, let's split this in parts:
First, select the max date from the parent
table, grouping by month:
select max(`date`) as max_date from parent group by last_day(`date`)
-- The "last_day()" function returns the last day of the month for a given date
Then, select the corresponding row from the parent table:
select parent.*
from parent
inner join (select max(`date`) as max_date from parent group by last_day(`date`)) as a
on parent.`date` = a.max_date
Finally, select the corresponding rows in the child
table:
select child.*
from child
inner join parent
on child.parent_id = parent.id
inner join (select max(`date`) as max_date from parent group by last_day(`date`)) as a
on parent.`date` = a.max_date;
You can check how this works on this SQL fiddle.
EDIT
The above solution works, but if your tables are big, you may face a problem because the joined data is not indexed. One way to solve this is to create a temporary table and use this temp table to get your final result:
drop table if exists temp_max_date;
create temporary table temp_max_date
select max(`date`) as max_date
from parent
group by last_day(`date`);
alter table temp_max_date
add index idx_max_date(max_date);
-- Get the final data:
select child.*
from child
inner join parent
on child.parent_id = parent.id
inner join temp_max_date as a
on parent.`date` = a.max_date;
Here's the SQL fiddle for this second solution.
Temporary tables are only accesible to the connection that creates them, and are destroyed when the connection is closed or killed.
Remember: Add the appropriate indexes to your tables.

- 20,547
- 13
- 65
- 83
Use this SQL:
SELECT * FROM Child WHERE PARENT_ID IN (
SELECT MAX(ID) FROM Parent GROUP BY LAST_DAY(DATE)
)
Here is the working SQL Fiddle: http://sqlfiddle.com/#!9/d8880/8

- 33,439
- 20
- 81
- 132
-
1This assume `ID` Increase according to `DATE`. That isnt always true – Juan Carlos Oropeza Nov 20 '15 at 21:45
This solution is clunky in its inability to properly employ indexes, but it's easier to write than one that would...
SELECT a.*
, c.id
FROM parent a
JOIN
( SELECT DATE_FORMAT(date,'%Y-%m')yearmonth
, MAX(date) max_date
FROM parent
GROUP
BY yearmonth
) b
ON b.max_date = a.date
JOIN child c
ON c.parent_id = a.id;

- 33,750
- 13
- 40
- 57