MySQL
Database Management
SQL Queries
Data Retrieval
Record Management

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.

Practice system design

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

  1. GROUP BY - This clause is used in SQL to group rows that have the same values in specified columns into summary rows.
  2. 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.
  3. 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:

sql
1SELECT *
2FROM transactions AS outer_trans
3JOIN (
4    SELECT MAX(transaction_id) AS last_transaction_id
5    FROM transactions
6    GROUP BY customer_id
7) AS max_transactions ON outer_trans.transaction_id = max_transactions.last_transaction_id;

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:

sql
1SELECT a.*
2FROM transactions a
3WHERE a.transaction_id IN (
4    SELECT MAX(b.transaction_id)
5    FROM transactions b
6    GROUP BY b.customer_id
7);

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:

sql
1SET @customer_id = NULL, @rn = 0;
2
3SELECT *
4FROM (
5    SELECT transactions.*,
6           @rn := IF(@customer_id = customer_id, @rn + 1, 1) AS rownumber,
7           @customer_id := customer_id AS dummy
8    FROM transactions
9    ORDER BY customer_id, transaction_date DESC
10) ranked
11WHERE ranked.rownumber = 1;

In this example:

  • Records are sorted by customer_id and transaction_date in descending order.
  • A row number is assigned to each row, which is reset every time customer_id changes.

Performance Considerations

  • Indexes: Ensure that columns used in JOIN, WHERE, and ORDER BY clauses 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

MethodUse CaseAdvantagesDisadvantages
Subquery with MAX()Simple scenarios with direct max identifierSimple and intuitiveCould be inefficient with large datasets
Subquery in WHERE ClauseSimilar to the first but slight variation in syntaxStraightforward and standard among SQL usersPotentially slow depending on the dataset
Using VariablesWhen needing sequential processing of rowsHighly customizableComplex 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
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track 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.

Practice system design

All Rights Reserved.