Laravel join with limit
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Mastering Laravel Joins: How to Get the Latest Record from a One-to-Many Relationship
As developers working with relational databases in Laravel, performing complex joins is a daily task. Often, we need to combine data from multiple tables, but when dealing with one-to-many relationships—like linking clients to their many recharge records—we run into a common performance and data integrity challenge: how do you select only the most relevant record?
This post addresses a specific scenario where you are trying to join clients with radusergroup (one-to-one) and recharge (one-to-many), but you only want the single, latest entry from the recharge table for each client. Standard LEFT JOINs will result in massive data duplication, leading to incorrect pagination results.
The Pitfall of Simple Joins
Your existing query structure looks like this:
$query = DB::table('clients')
->leftJoin('radusergroup', 'clients.username', '=', 'radusergroup.username')
->leftJoin('recharge', 'clients.username', '=', 'recharge.soldto');
// This returns all possible rows from the recharge table, causing duplication.
When you join a one-to-many relationship directly using JOIN, if a client has three recharge records, that client's data is duplicated three times in the result set. When you paginate this result, you end up showing irrelevant, duplicate data instead of just the latest transaction. This isn't a failure of the SQL syntax itself, but a failure in data selection strategy for your business requirements.
The Solution: Selecting the Latest Record Efficiently
To solve this, we need an intermediate step to identify which recharge record is the most recent before joining it back to the main tables. There are two primary, robust methods for achieving this in Laravel/SQL: using a correlated subquery or leveraging Window Functions.
Method 1: Using a Correlated Subquery (The Practical Approach)
A very practical way to solve this is to first find the maximum date (or ID, if you have an auto-incrementing primary key) for each client in the recharge table and then join back only those specific records.
We can use a subquery to filter the recharge table down to just the latest entry per group:
$latestRecharges = DB::table('recharge')
->select('soldto', DB::raw('MAX(id) as max_id'))
->groupBy('soldto');
$query = DB::table('clients')
->leftJoin('radusergroup', 'clients.username', '=', 'radusergroup.username')
// Join only with the filtered, latest records from the subquery
->leftJoinSub($latestRecharges, 'latest_recharge', function ($join) {
$join->on('clients.username', '=', 'latest_recharge.soldto');
});
Why this works: The leftJoinSub effectively pre-filters the recharge table to only include one row per client (the one with the maximum ID), eliminating the duplication issue before the final pagination step. This approach keeps the query highly optimized, which is a key principle when developing complex data interactions in Laravel.
Method 2: Using Window Functions (ROW_NUMBER()) (The Advanced Approach)
For very large datasets or more complex ranking requirements, Window Functions are superior. You can assign a rank to every recharge record partitioned by the client, and then filter only for rank 1.
$query = DB::table('recharge')
->select('*')
->whereRaw("ROW_NUMBER() OVER(PARTITION BY soldto ORDER BY id DESC) = 1") as latest_recharge_id;
// Now join this filtered set back to clients and radusergroup
$finalQuery = DB::table('clients')
->leftJoin('radusergroup', 'clients.username', '=', 'radusergroup.username')
->leftJoinSub(
$query,
'latest_recharge',
function ($join) {
$join->on('clients.username', '=', 'latest_recharge.soldto');
}
);
Window functions provide a powerful, single-pass way to identify the "top N" records within defined groups, which is often more performant than self-joins or complex nested subqueries when dealing with large tables. As you build sophisticated data layers with Laravel, understanding these advanced SQL concepts will make your ORM usage much more powerful.
Conclusion
When joining tables in Laravel, especially those involving one-to-many relationships where you only need a single representative record (like the latest entry), avoid simple, broad JOINs if they lead to duplication. Instead, employ smart filtering techniques like correlated subqueries or Window Functions (ROW_NUMBER()) to pre-select the relevant data before performing the final join. This practice ensures your queries are efficient, scalable, and provide accurate results for your application, aligning perfectly with the principles of clean coding advocated by the Laravel team.