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
相关产品推荐
相关产品推荐

