Laravel get latest record for each group

后端 未结 1 782
半阙折子戏
半阙折子戏 2021-01-19 10:59

I am trying to migrate some Raw SQL to an Eloquent (or Query Builder) scope on my model. My Parts history table looks like this:

+----+---------+--------+---         


        
相关标签:
1条回答
  • 2021-01-19 11:06

    You could rewrite your query as left join to get the same results

    select a.* 
    from part_histories a
    left join part_histories b on a.part_id = b.part_id 
                                and a.created_at < b.created_at
    where b.part_id is null
    

    and I guess you can transform easily above query in your scope something like

    public function scopeWithLatestStatus($query)
    {
        return $query->leftJoin('part_histories as b', function ($join) {
                    $join->on('a.part_id', '=', 'b.part_id')
                         ->where('a.created_at', '<', 'b.created_at');
                })
            ->whereNull('b.part_id')
            ->from('part_histories as a')
            ->select('a.*');
    }
    

    Laravel Eloquent select all rows with max created_at

    Laravel - Get the last entry of each UID type

    Laravel Eloquent group by most recent record

    Edit using above query as has relation,To get the latest history for each part you can define a hasOne relation like

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Support\Facades\DB;
    class Part extends Model
    {
        public function latest_history()
        {
            return $this->hasOne(\App\Models\PartHistory::class, 'part_id')
                ->leftJoin('part_histories as p1', function ($join) {
                    $join->on('part_histories.part_id', '=', 'p1.part_id')
                        ->whereRaw(DB::raw('part_histories.created_at < p1.created_at'));
                })->whereNull('p1.part_id')
                ->select('part_histories.*');
        }
    }
    

    And then to load parts with their latest history you could eager load above defined mapping as

    $parts = Part::with('latest_history')->get();
    

    You will have a list of parts along with latest history as

    Array
    (
        [0] => Array
            (
                [id] => 1
                [title] => P1
                [latest_history] => Array
                    (
                        [id] => 6
                        [created_at] => 2018-06-16 08:25:10
                        [status] =>  1
                        [part_id] => 1
                    )
    
            )
    ....
    )
    
    0 讨论(0)
提交回复
热议问题