Laravel从一对多的关系中获得许多表的最后一行值

时间:2018-06-15 23:56:26

标签: laravel-5 eloquent greatest-n-per-group

我正在构建一个具有一对多关系模型的应用程序。在模型中,学生表与学生地址详细信息有一对多的关系。我想从地址详细信息表中检索最后一行。我被困在如何检索数据。我无法在本网站上找到类似的答案。

我目前的解决方案是

$students = Student::with('visaDetails', 'addresses', 'instituteDetails', 'subAgents',
            'staffDetails', 'commissionDetails', 'comments')->paginate(16);

        foreach ($students as $student){
            foreach ($student->addresses as $address){
                dd($address->id);
            }
        }

我的学生模型如下

class Student extends Model
{
    //One to Many relation to student address

    public function addresses(){
        return $this->hasMany('App\Model\Address');
    }
}

但随着记录数量呈指数增长,这种解决方案效率不高。 另外,我还需要为其他许多表找到最后一行。

如果有人能帮助我那么这将是非常好的。

2 个答案:

答案 0 :(得分:1)

要从每个学生的地址表中获取最新记录,您可以使用以下自加入查询

select s.*, l.*
from students s
join address a on s.id = a.student_id
left join address a1 on a.student_id = a1.student_id
and a.created_at < a1.created_at
where a1.student_id is null

我认为最新的方式是您需要具有最新created_at属性的地址。

使用查询构建器,您可以将其重写为

DB::table('students as s')
  ->select('s.*', 'a.*')
  ->join('address as a', 's.id', '=', 'a.student_id')
  ->leftJoin('address as a1', function ($join) {
        $join->on('a.student_id', '=', 'a1.student_id')
             ->whereRaw(DB::raw('a.created_at < a1.created_at'));
   })
  ->whereNull('a1.student_id')
  ->get();

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

答案 1 :(得分:0)

我创建了一个程序包,可让您限制每个父级渴望加载的结果的数量:
https://github.com/staudenmeir/eloquent-eager-limit

在父模型和相关模型中都使用preset-stage-x特性。

{
    test: /\.js$/,
    use: {
    loader: 'babel-loader',
    options: {
        presets: [
            '@babel/preset-env',
        ],
        plugins: [
            'transform-class-properties',
            '@babel/plugin-transform-runtime'
        ]
    }
}

然后,您可以将HasEagerLimit应用于您的关系:

class Student extends Model {
    use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}

class Address extends Model {
    use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}