Pulling every row into PHP just to count them, sum a column, or find a maximum value is unnecessary — Eloquent's aggregate methods push that calculation down to the database instead, and each one returns a single scalar value directly, not a Collection that then needs to be reduced in application code.
1. count()
$total = Order::count();
$pending = Order::where('status', 'pending')->count();
count() executes a SELECT COUNT(*) query — it doesn't fetch any rows at all, just the count, which is significantly cheaper than Order::all()->count() (which would pull every full row from the database only to count them in PHP afterward).
2. sum()
$totalRevenue = Order::where('status', 'completed')->sum('total');
3. avg()
$averageOrderValue = Order::avg('total');
// alias: Order::average('total');
4. min() and max()
$cheapest = Product::min('price');
$mostExpensive = Product::max('price');
5. Combining aggregates with other query constraints
$revenueThisMonth = Order::where('status', 'completed')
->whereMonth('created_at', now()->month)
->sum('total');
Every aggregate method respects whatever where clauses and other constraints are chained before it — the aggregate applies to the filtered result set, exactly as it would in a hand-written SQL query with a matching WHERE clause.
6. Aggregating within groups
$revenueByStatus = Order::select('status', DB::raw('SUM(total) as total_revenue'))
->groupBy('status')
->get();
foreach ($revenueByStatus as $row) {
echo "{$row->status}: {$row->total_revenue}";
}
The dedicated aggregate methods (sum(), avg(), etc.) return one overall value across the whole query — computing a separate total per group instead needs a raw SELECT with GROUP BY, since there's no built-in "grouped sum" shorthand method.
7. Aggregating a relationship's count without loading it
$users = User::withCount('posts')->get();
foreach ($users as $user) {
echo "{$user->name}: {$user->posts_count} posts";
}
withCount() adds a {relation}_count attribute to each model via a single efficient subquery, without loading the related records themselves — the right tool when only the count is needed (a "5 posts" badge next to a user's name), rather than eager-loading the full related collection just to call ->count() on it in a loop.
8. Aggregates via a relationship directly
$user->posts()->count();
$user->orders()->sum('total');
Calling an aggregate method directly on a relationship (rather than on the base model query) automatically scopes it to just that specific related model's records — no manual where('user_id', $user->id) needed, since the relationship definition already carries that constraint.