Use query builder subqueries inside orderBy() and orderByDesc() to sort models by aggregated or related table columns directly in SQL.
Sorting records by related data (such as sorting users by the date of their latest login, or ordering categories by their total sales) often leads developers to sort Eloquent collections in PHP memory using sortBy().
Sorting in memory requires loading all records into RAM and breaks database pagination. You can pass a subquery directly to orderBy().
Sorting by a Related Subquery
use App\Models\Order;
use App\Models\User;
// Sort users by the timestamp of their most recent order
$users = User::orderByDesc(
Order::select('created_at')
->whereColumn('orders.user_id', 'users.id')
->latest()
->limit(1)
)->paginate(20);
Sorting by Calculated Aggregate Subquery
use App\Models\Book;
use App\Models\Review;
// Sort books by their average rating
$books = Book::orderByDesc(
Review::selectRaw('AVG(rating)')
->whereColumn('reviews.book_id', 'books.id')
)->paginate(15);
Summary
- Executes sorting directly inside the database engine before pagination limits apply.
- Works directly with
paginate()and preserves minimal memory footprints. - Eliminates the need to load large collections into PHP memory just for sorting.
Related Tips
View all tips →Optimize Date Queries by Replacing whereYear() with whereBetween()
Replace whereYear() and whereMonth() on large database tables with whereBetween() date ranges to enable SQL index lookups.
Efficient Unique Slug Generation in Eloquent Without Looping Queries
Generate unique database slugs in Eloquent by querying the maximum existing numerical suffix directly instead of executing repeated queries in a while loop.