Retrieving the last record in each group - MySQL
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
When working with relational databases like MySQL, a common query scenario is retrieving the last record from each group of data based on certain criteria. This requirement can arise in various situations such as fetching the latest order of each customer, the last payment made by each user, or the most recent status update for each application.
Understanding the Scenario
The task is shaping a SQL query that can efficiently group records based on a certain field and then fetch the last record in each of those groups according to a specified criterion, typically a time stamp or an incrementing ID.
SQL Concepts Involved
- GROUP BY - This clause is used in SQL to group rows that have the same values in specified columns into summary rows.
- ORDER BY - This clause is used to sort the result set by one or more columns, and it can sort in ascending or descending order.
- JOIN - A JOIN clause is used to combine rows from two or more tables, based on a related column between them.
Approaches to Retrieve Last Record in Each Group
1. Using a Subquery with MAX()
The most straightforward approach is to use a subquery that identifies the maximum value of the identifying column (e.g., date, ID) for each group.
Example:
In this example:
- The inner query gets the highest (last) transaction ID for each customer.
- The outer query then retrieves the rows that have these IDs.
2. Using a Subquery in the WHERE Clause
This approach is similar but places the subquery directly in the WHERE clause to filter the main query.
Example:
3. Using Variables to Simulate ROW_NUMBER
MySQL does not naturally support the SQL standard ROW_NUMBER() function (until 8.0), so users on older versions can use session variables to emulate this functionality.
Example:
In this example:
- Records are sorted by
customer_idandtransaction_datein descending order. - A row number is assigned to each row, which is reset every time
customer_idchanges.
Performance Considerations
- Indexes: Ensure that columns used in
JOIN,WHERE, andORDER BYclauses are indexed appropriately to speed up query execution. - Query Complexity: The queries should be as simple as possible to execute quickly and use server resources efficiently. Avoid nested joins and subqueries if a simpler query can achieve the same result.
Summary Table
| Method | Use Case | Advantages | Disadvantages |
Subquery with MAX() | Simple scenarios with direct max identifier | Simple and intuitive | Could be inefficient with large datasets |
| Subquery in WHERE Clause | Similar to the first but slight variation in syntax | Straightforward and standard among SQL users | Potentially slow depending on the dataset |
| Using Variables | When needing sequential processing of rows | Highly customizable | Complex and less readable |
Conclusion
Selecting the last record in each group in MySQL can be achieved through several methods, each with its own set of trade-offs concerning performance, complexity, and MySQL version compatibility. The choice of method largely depends on the specific requirements and constraints of the project you are working on.
Related reading
- Retrieving the last record in each group - MySQL
- Return 0 if field is null in MySQL
- RHEL environments in YugaByte DB
- Riak on top of LevelDB
- Ridiculously slow writes to Amazon DynamoDB PHP API
- Right database for machine learning on 100 TB of data
- Rolling upgrades in YugaByte DB - is it possible?
- Room - Schema export directory is not provided to the annotation processor so we cannot export the schema

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.