MySQL JOIN the most recent row only?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Joining only the most recent related row is a classic SQL pattern sometimes called "greatest-n-per-group." The correct query depends on your MySQL version and on how you define "most recent" when two rows share the same timestamp. Once that rule is explicit, the join becomes much easier to write correctly.
The Problem Setup
Suppose you have customers and orders, and you want each customer joined to only their latest order.
The wrong approach is a plain join, because that returns every matching order, not just the newest one.
MySQL 8.0+: Use ROW_NUMBER()
If you have MySQL 8.0 or later, window functions make this much cleaner.
This is usually the clearest answer. The ranking step says exactly how "most recent" is decided.
Why The Extra id DESC Helps
If two orders have the same created_at, ordering by timestamp alone leaves a tie. Adding id DESC gives the query a deterministic winner.
Without that tie-breaker, you can get inconsistent results when several rows share the same latest timestamp.
Older MySQL: Join Against A Max-Date Subquery
If window functions are not available, use a derived table that finds the maximum timestamp per parent row.
This works, but it can still return multiple rows per customer if two orders share the same latest timestamp. That is why deterministic tie-breaking matters.
Older MySQL With Tie-Breaking
If ties matter and you do not have window functions, you may need a second layer of aggregation or a correlated subquery.
This is often easier to read than stitching together several derived tables, and with the right index it can perform well.
Indexing Matters
Whichever form you choose, this index is usually important:
Without a supporting index, MySQL may scan far more rows than necessary for each customer.
Decide Whether You Need LEFT JOIN Or INNER JOIN
Use LEFT JOIN if customers without orders should still appear with NULL order columns. Use INNER JOIN if only customers with at least one order should be returned.
That is a business-rule decision, not just a query-style preference.
Common Pitfalls
- Writing a normal join and then being surprised that all related rows appear.
- Using
MAX(created_at)without a tie-breaker and getting duplicate "latest" rows. - Forgetting that MySQL 8.0 window functions simplify this pattern substantially.
- Using
INNER JOINwhen rows with no related record should still be listed. - Ignoring indexes and then blaming the SQL pattern for poor performance.
Summary
- Joining only the latest related row is a greatest-n-per-group problem.
- In MySQL 8.0+,
ROW_NUMBER()is usually the clearest solution. - In older MySQL, use a max-date subquery or a correlated subquery.
- Add a tie-breaker such as
id DESCwhen timestamps can be equal. - Index by parent key and recency columns to keep the query efficient.
Related reading

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.