Laravel Where Count > N

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Laravel Where Count > N: Mastering Relationship Filtering with Eloquent

As developers working with relational data in Laravel, managing complex filtering based on the number of related records is a common requirement. When you have a many-to-many relationship, like between Customer and Car, finding customers who possess fewer than $N$ cars requires careful use of Eloquent's querying capabilities.

Let’s dive into the scenario you presented: finding all customers who have less than 2 cars, where the threshold (2) is dynamic. We will analyze why your initial attempt might have failed and explore the most robust, performant solutions available in the Laravel ecosystem.

The Challenge: Filtering Based on Related Record Counts

You have two models, Customer and Car, linked by a pivot table. You need to query for customers where the count of associated cars is less than a variable number ($N$).

Your initial attempt using whereHas with a raw subquery is a valid approach, but it can sometimes be overly complex or inefficient when dealing with simple aggregations.

php
// Your original attempt (which didn't work as expected)
$customers = Customer::whereHas("cars", function($query) {
    $query->selectRaw("count(*) < ?", [2]);
})->get();

While this structure attempts to filter the related relationship, often when mixing whereHas with complex aggregate functions within it, Eloquent’s query builder can struggle to translate it into the most optimized SQL.

Solution 1: The Idiomatic Eloquent Approach using withCount

For filtering based on counts, the most idiomatic and often clearest way in Laravel is to utilize the withCount method first. This pre-calculates the count for every related model, making subsequent filtering straightforward using a standard where clause.

This approach separates the counting logic from the main filtering logic, leading to cleaner code and better readability. It aligns perfectly with the principle of keeping Eloquent relationships simple while leveraging the database's power.

Here is how you implement finding customers with less than $N$ cars:

php
$threshold = 2;

$customers = Customer::withCount('cars')
    ->where('cars_count', '<', $threshold)
    ->get();

Explanation of the withCount Method

  1. withCount('cars'): This instructs Eloquent to perform a LEFT JOIN and aggregate the results, creating a new column (named cars_count by default) on the customers table that holds the total number of related records from the cars table for each customer.
  2. where('cars_count', '<', $threshold): We then apply a standard Eloquent where clause directly against this newly created, aggregated column. This is highly performant because the database handles the counting aggregation before the filtering step.

This method is excellent practice for any complex data retrieval in Laravel, promoting clean separation of concerns—a core tenet reflected in how high-quality frameworks like Laravel are designed to operate.

Solution 2: The Pure SQL Approach (For Maximum Performance)

If performance on extremely large datasets becomes a critical concern, or if you need more complex aggregations that Eloquent struggles to map cleanly, falling back to explicit database joins and grouping can offer superior speed. This approach directly leverages raw SQL power.

php
$threshold = 2;

$customers = DB::table('customers')
    ->join('customer_cars', 'customers.id', '=', 'customer_cars.customer_id')
    ->select('customers.*')
    ->groupBy('customers.id')
    ->having(DB::raw('COUNT(customer_cars.car_id)'), '<', $threshold)
    ->get();

While this requires writing raw SQL, it is the most direct translation of the relational algebra you need. For simple