7

I have 2 models in my app:

1. Customer.php

2. Car.php

Now I would like to run a query that returns all customers that have less than 2 cars. Where 2 is a number that can be changed by the user.

I have tried this but it didn't work, it just returns all customer records:

$customers = Customer::whereHas("cars", function($query) { $query->selectRaw("count(*) < ?", [2]); }) ->get(); 

Edit: The two models are linked in a pivot table, meaning A customer can have more than 1 car and a Car can belong to more than 1 customer.

4 Answers 4

39

Use this:

$customers = Customer::withCount('cars') ->having('cars_count', '<', 2) ->get(); 
Sign up to request clarification or add additional context in comments.

4 Comments

Actually this works now, didn't work before because my relation wasn't setup correctly.
This only works if the query was grouped by, otherwise it throws unknown column cars_count.
And how do you group by the query? This answer is incomplete, it doesn't work as is
'cars_count' alias is already created by the 'withCount' function @Ken
5

So , here is the result.

Relation in model Customer.php

public function cars() { return $this->belongsToMany('App\Car','car_customer','car_id','customer_id'); } 

Query to get all customers with N cars:

 $userInput = 2; $data = Customer::with('cars') ->withCount('cars') ->has('cars', '<', $userInput) ->orderBy('cars_count', 'desc') ->get(); 

Where the $userInput is your 'N'.

8 Comments

This will work, but Jonas' solution is strictly better since this one executes 1 more subquery.
Jonas' soution will say that there is no column 'cars_count'
Not if the relation is set up correctly. If it isn't this won't work either. Also, why would you expect ->orderBy('cars_count') to work if there's no column cars_count? As for the explanation, ->withCount('cars') adds a cars_count to the select. It makes a subquery that counts the relation.
Thanks, this worked, @devk was right, Jonas's answer didn't work for me initially since my relations were not setup correctly, thanks for your help o/
@user3718908 ,whereHas() is the same as has() , but whereHas() allows to specify additional filters on related model , has() filters selecting model based on a relation.
|
4

This is the best way:

$customers = Customer::has('cars','<', 2)->get(); 

2 Comments

Hi and welcome! Please explain why this is the best solution in your opinion.
Because its simple , one line code and you don`t have to load any relation or using "having" query.
-1

Have you tried this approach?

$input = 2; $customers = Customer::whereHas("cars", function($query) use ($input) { $query->where(DB::raw("count(cars.id)"), "<", DB::raw($input)) })->get(); 

5 Comments

No I haven't, I forgot to add that Customer's and Cars are joined on a pivot table.
Please , provide a sqlfiddle.
It's just a belongsToMany relation. Meaning I have a customer_car pivot table in my database.
I know. But i need to write that query in raw sql , so i can write that query in laravel.
Please add some 3-4 rows for each table.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.