MySQL INNER JOIN select only one row from second table
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
A plain INNER JOIN returns every matching row from the second table, so it cannot by itself choose only one child row in a one-to-many relationship. To get one row, you first need a deterministic rule such as latest, earliest, highest priority, or lowest price. Once that rule is defined, the SQL pattern becomes much easier to write correctly.
Why a Normal Join Returns Too Many Rows
Suppose each order can have many payments. A simple join returns one result row for every matching payment.
If order 10 has three matching payment rows, you will get three result rows for that order. That is correct SQL behavior, but it is not what you want when the requirement says "only one row from the second table".
MySQL 8 Solution with ROW_NUMBER()
In MySQL 8, the cleanest solution is usually a window function. Rank the child rows per parent, then keep only rank 1.
This query says: within each order, sort the payments by newest timestamp and then by largest id as a tie-breaker. Keep only the first ranked row.
Pre-MySQL 8 Pattern with Aggregation
If window functions are not available, choose the target row in a subquery and then join back to the real table.
This works, but it may still return multiple rows if two payments share the same timestamp. If you truly need exactly one row, you still need a secondary tie-break rule.
Correlated Subquery Option
Another readable option is a correlated subquery that selects the child row id directly.
This is often easy to understand because the business rule is visible in one place. Performance depends heavily on indexing and data volume.
Index for the Selection Rule
No matter which query form you choose, index the child table according to the join and ordering pattern.
That index helps MySQL find the relevant child rows quickly and reduces the cost of ordering or scanning within each parent group.
Common Pitfalls
The most common mistake is trying to solve a one-to-many selection problem with DISTINCT. That may remove duplicate result rows, but it does not define which child row should win.
Another issue is saying "latest row" without a tie-breaker. If two rows share the same timestamp, the query may return more than one row or pick an arbitrary row depending on the pattern you used.
It is also easy to choose a SQL technique before deciding the business rule. The database cannot guess whether "one row" means newest payment, approved payment, primary address, or highest score.
Finally, do not ignore indexing. A correct query can still become painfully slow if the child table is large and there is no supporting index for the parent key and ordering columns.
Summary
- A plain
INNER JOINreturns all matching child rows, not just one. - Decide first which child row you want to keep and express that rule explicitly.
- In MySQL 8,
ROW_NUMBER()is usually the clearest solution. - In older MySQL versions, use aggregation or a correlated subquery with a deterministic tie-breaker.
- Add indexes that match the join key and row-selection order so the query scales.
Related reading
- MySQL InnoDB not releasing disk space after deleting data rows from table
- MySQL Insert into multiple tables? Database normalization?
- mySQL insert into table, data from another table?
- MySQL INSERT INTO table VALUES.. vs INSERT INTO table SET
- MySQL JOIN the most recent row only?
- MySQL Large VARCHAR vs. TEXT?
- MySQL Insert query doesn't work with WHERE clause
- MySQL Insert record if not exists in table

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.