如何将指定SQL查询转换为Laravel Eloquent查询?
用Laravel Eloquent实现指定条件的学生查询
以下是几种对应你原生SQL逻辑的Eloquent实现方案:
方法一:直接映射原生SQL的whereExists写法
这种写法完全复刻你提供的原生SQL逻辑,通过whereExists嵌套子查询实现:
use Illuminate\Support\Facades\DB; $someDate = '2022-05-05'; // 注意使用标准Y-m-d日期格式 $students = Student::whereExists(function ($query) use ($someDate) { $query->select(DB::raw(1)) // 内层子查询:获取每个学生最新的未删除Movement ->fromSub(function ($subQuery) { $subQuery->select('student_movements.id', 'student_movements.direction', 'student_movements.date') ->from('student_movements') ->join('student_student_movements', 'student_movements.id', '=', 'student_student_movements.student_movement_id') // 关联外层students表的id ->whereColumn('students.id', 'student_student_movements.student_id') ->whereNull('student_movements.deleted_at') // 按id倒序取最新一条记录 ->orderByDesc('student_movements.id') ->limit(1); }, 'last_sm') // 筛选最新Movement的条件 ->where('last_sm.direction', 1) ->where('last_sm.date', '>=', $someDate); })->get();
方法二:新增关联简化查询
在Student模型中定义一个获取最新未删除Movement的关联,后续可复用该关联进行查询:
第一步:在Student模型中添加关联
// app/Models/Student.php use Illuminate\Database\Eloquent\Relations\BelongsToMany; public function latestStudentMovement(): BelongsToMany { return $this->belongsToMany(StudentMovement::class, 'student_student_movements') ->whereNull('student_movements.deleted_at') // 按id倒序,仅取最新一条 ->latest('student_movements.id') ->limit(1); }
第二步:使用whereHas查询满足条件的学生
$someDate = '2022-05-05'; $students = Student::whereHas('latestStudentMovement', function ($query) use ($someDate) { $query->where('direction', 1) ->where('date', '>=', $someDate); })->get();
方法三:通过分组获取最新Movement ID后筛选
先通过分组查询获取每个学生的最新未删除Movement ID,再通过whereHas关联筛选条件:
use Illuminate\Support\Facades\DB; $someDate = '2022-05-05'; // 获取每个学生的最新未删除Movement ID $latestMovementIds = StudentMovement::select(DB::raw('MAX(id) as id')) ->join('student_student_movements', 'student_movements.id', '=', 'student_student_movements.student_movement_id') ->whereNull('student_movements.deleted_at') ->groupBy('student_student_movements.student_id'); // 查询满足条件的学生 $students = Student::whereHas('studentMovements', function ($query) use ($latestMovementIds, $someDate) { $query->whereIn('student_movements.id', $latestMovementIds) ->where('direction', 1) ->where('date', '>=', $someDate); })->get();
注意事项
- 确保日期格式为
Y-m-d标准格式,避免数据库解析错误; - 若
student_movements的date字段比id更适合判断"最新",可将排序条件改为orderByDesc('student_movements.date'); - 方法二的关联复用性更强,方法一严格匹配原生SQL逻辑,可根据场景选择。
内容的提问来源于stack exchange,提问作者trolik
相关产品推荐
相关产品推荐

