Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use DISTINCT in Laravel's withCount() method

With Laravel/Lumen eloquent I can get count relations like this:

User::withCount('views')->get();

this will use SQL

select `users`.*, (select count(*) from `views` where `users`.`id` = `views`.`user_id`) as `views_count` from `users`

and return all models with views_count attribute, great.

But I need these views counted with unique IP column. In this query I could simple replace count(*) with count(DISTINCT ip) like this:

select `users`.*, (select count(DISTINCT ip) from `views` where `users`.`id` = `views`.`user_id`) as `views_count` from `users`

and in phpMyAdmin it returns good results. But how achieve this in Laravel eloquent? I cannot find any way to use custom column for count. I can pass array with query function like this:

User::withCount(['views' => function ($q) { // what there? }])->get();

but now I can pass only where conditions, not use Distinct in any way.

I know I can first get models, and then foreach with distinct and count or groupby but I need to keep this single query, fast and simple. And if I can easy achieve this in raw SQL then I also should do this in Laravel somehow. I can use some custom eloquent method if required because I will use this unique count in many places in applications.

So short question - how to combine withCount and Distinct?

PS I also tried to use distinct or groupBy on on model's relation level (on hasMany) but this does not work.

like image 746
norr Avatar asked Jul 06 '19 13:07

norr


People also ask

What is the use of withcount in Laravel?

In simple, the Laravel withCount () is used to count the rows present in the relational model and fetch the amount of associated or related records present in the main object. It can be implemented with many relationships like one-to-one, one to many, many to many, polymorphic relationship, querying relationship, dynamic relationship, and so on.

What is distinct in Laravel?

As mentioned in the previous paragraph, the Laravel statement of DISTINCT is a query that identifies the exact value of the search. It returns the value from the database through the following Eloquent Distinct method:

When to use a sub query in Laravel?

When you need to could a sub query Laravel provides a useful withCount method that is perfect. Take an example of a user can have records with a hasMany relationship: I have a model called BookingCandidate that links to the user by its filled_by_id that matches a user_id

How to replace count (*) with count (distinct IP) in a query?

In this query I could simple replace count (*) with count (DISTINCT ip) like this: select `users`.*, (select count (DISTINCT ip) from `views` where `users`.`id` = `views`.`user_id`) as `views_count` from `users`


Video Answer


2 Answers

User::withCount('views', function($query) {
    $query->select(DB::raw('count(distinct(ip))'));
})->get();
like image 160
HTMHell Avatar answered Sep 23 '22 00:09

HTMHell


Solution for Laravel 8.x

User::withCount(['views as views_count' => function($query) {
    $query->select(DB::raw('count(distinct(ip))'));
}])->get();

Note: Do not use selectRaw.

like image 21
Juan Lago Avatar answered Sep 27 '22 00:09

Juan Lago