8

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.

norr
  • 1,725
  • 1
  • 20
  • 33

2 Answers2

17
User::withCount('views', function($query) {
    $query->select(DB::raw('count(distinct(ip))'));
})->get();
HTMHell
  • 5,761
  • 5
  • 37
  • 79
13

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.

Kirk Beard
  • 9,569
  • 12
  • 43
  • 47
Juan Lago
  • 960
  • 1
  • 10
  • 20