简体   繁体   中英

Eloquent sub-query for if the row is the latest one

I have the following subquery:

->whereHas('statuses', function($query){
           $query->where('status_id', request('status'));
})->orderBy(...)->paginate();

For simplicity's sake I have hidden the full query. Let's say I have the pivot table user_status . User has many statuses and a status can also have many users (unusual, I know. Just consider it as an example). So when I query the pivot table user_status as described above, I get those rows that have the requested status id. But I also want to add the constraint that the row must be the latest one for that particular user (not in entire table). Here is how the user_status table looks like:

+---------+-----------+---------------------+
| user_id | status_id | created_at          |
+---------+-----------+---------------------+
|       1 |         1 | 2018-09-03 18:39:14 |
|       1 |         8 | 2018-09-03 18:51:42 |
+---------+-----------+---------------------+

In this scenario, if the requested status is 1 , I don't want this row to be returned, because status_id 1 is not the latest one for the user_id 1 (see the time difference in create_at column).

How can I achieve that?

You can achieve that by using another condition with a nested query.

->whereHas('statuses', function($query){
       $query->where('status_id', request('status'))
             ->whereIn('user_status.id', function($query) {
                $query->selectRaw('MAX(id)')
                      ->from('user_status')
                      ->groupBy('user_id');
             });
})->orderBy(...)->paginate();

The nested query will select only latest rows(assuming user_status.id is auto-increment )

I define a relation in user model as :-

public function latest_statuses() {
        return $this->hasMany(Status::class,'user_id','id')->orderBy('created_at','DESC')->take(1);
}

And after that written query as :-

$status = \App\User::with('latest_statuses')->whereHas('latest_statuses', function($query){
           return $query->where('status_id', 1);
        })->get();

It works for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM