You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中latest()与where()链式调用问题:筛选最新状态为1的学生

筛选最新关联状态为1的学生解决方案

你需要先锁定每个学生的最新关联状态记录,再判断该记录的status_id是否为1,以下是两种Eloquent实现方式:

方法1:子查询分组+关联筛选

// 先获取每个学生最新关联记录的创建时间
$latestStatusSubquery = DB::table('status_student')
    ->select('student_id', DB::raw('MAX(created_at) as latest_created_at'))
    ->groupBy('student_id');

// 筛选出最新状态为1的学生
$targetStudents = Student::whereHas('statusuri', function ($query) use ($latestStatusSubquery) {
    $query->joinSub($latestStatusSubquery, 'latest_status', function ($join) {
        // 关联中间表和子查询,锁定每个学生的最新记录
        $join->on('status_student.student_id', '=', 'latest_status.student_id')
             ->on('status_student.created_at', '=', 'latest_status.latest_created_at');
    })
    // 仅保留最新记录status_id为1的学生
    ->where('status_id', 1);
})->get();

方法2:whereExists子查询

$targetStudents = Student::whereExists(function ($query) {
    $query->select(DB::raw(1))
          ->from('status_student')
          // 关联当前学生ID
          ->whereColumn('status_student.student_id', 'students.id')
          // 限定该记录是当前学生的最新关联记录
          ->where('status_student.created_at', function ($subquery) {
              $subquery->select(DB::raw('MAX(created_at)'))
                       ->from('status_student as ss')
                       ->whereColumn('ss.student_id', 'students.id');
          })
          // 判断最新记录的status_id是否为1
          ->where('status_id', 1);
})->get();

原查询问题说明

你之前的whereHas逻辑是先筛选所有status_id=1的记录,再取每个学生的最新那条,这会导致:如果学生曾经有过status_id=1的记录,但最新状态不是1,依然会被选中。而上述两种方法都是先锁定每个学生的最新关联记录,再判断该记录的status_id是否符合要求,完全匹配你的需求。

内容的提问来源于stack exchange,提问作者Octavian Niculescu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:31:05