如何将原生SQL转换为Laravel查询构造器?求助解决查询无结果问题
问题:将原生SQL转换为Laravel查询构造器代码
我需要把下面的原生SQL转换成Laravel查询构造器代码,请求帮忙:
SELECT id, `leave_name`, `total_leave_days`, leave_id, leave_taken_days FROM `leaves` AS t1 INNER JOIN ( SELECT leave_id, SUM(`leave_taken_days`) AS leave_taken_days FROM `leave_applications` WHERE user_id = 2 AND statuses_id = 2 GROUP BY leave_id ) AS t2 ON t1.id = t2.leave_id
我自己试了下面的代码,但完全没有输出结果:
$user_leaves = DB::table('leaves') ->select('id', 'leave_name', 'total_leave_days', 'leave_id', 'leave_taken_days') ->join('leave_application', 'leave_application.leave_id', '=', 'leave.id') ->select('leave_application.leave_id', DB::raw("SUM(leave_taken_days) as leave_application.leave_taken_days")) ->where('user_id','=', 2) ->where('statuses_id','=', 2) ->get();
更新:模型关联关系
- Leave模型
public function leave_application() { return $this->belongsTo(LeaveApplication::class, 'id' , 'leave_id'); }
- LeaveApplication模型
public function leave() { return $this->belongsTo(Leave::class, 'leave_id', 'id'); }
解决方案
方法一:还原原生SQL的子查询关联逻辑
直接用Laravel的joinSub方法实现原生SQL的子查询关联逻辑,代码如下:
// 先定义子查询:统计符合条件的各假期类型已使用天数 $subQuery = DB::table('leave_applications') ->select('leave_id', DB::raw('SUM(leave_taken_days) as leave_taken_days')) ->where('user_id', 2) ->where('statuses_id', 2) ->groupBy('leave_id'); // 主表关联子查询获取最终数据 $user_leaves = DB::table('leaves as t1') ->select('t1.id', 't1.leave_name', 't1.total_leave_days', 't2.leave_id', 't2.leave_taken_days') ->joinSub($subQuery, 't2', function ($join) { $join->on('t1.id', '=', 't2.leave_id'); }) ->get();
方法二:修正模型关联后用关联查询实现
首先纠正你的模型关联逻辑:一个假期类型对应多个申请记录,所以Leave和LeaveApplication是一对多关系,关联定义需要修改:
- Leave模型
public function leaveApplications() { return $this->hasMany(LeaveApplication::class, 'leave_id', 'id'); }
- LeaveApplication模型
public function leave() { return $this->belongsTo(Leave::class, 'leave_id', 'id'); }
修正后,用关联查询+聚合的方式实现需求:
$user_leaves = Leave::query() ->select('leaves.id', 'leaves.leave_name', 'leaves.total_leave_days', DB::raw('SUM(leave_applications.leave_taken_days) as leave_taken_days')) ->join('leave_applications', 'leaves.id', '=', 'leave_applications.leave_id') ->where('leave_applications.user_id', 2) ->where('leave_applications.statuses_id', 2) ->groupBy('leaves.id', 'leaves.leave_name', 'leaves.total_leave_days') ->get();
你的代码问题分析
- 表名错误:原生SQL中是
leave_applications,你写成了leave_application,导致关联的表不存在 - 重复select覆盖字段:连续调用
select()会替换之前的字段选择,最终只保留最后一次的字段,主表的id、leave_name等字段无法被查询 - 逻辑不符:原生SQL是先对子表聚合分组再关联,你的代码直接join后聚合,缺少分组操作且逻辑不一致
内容的提问来源于stack exchange,提问作者Jhyaps
相关产品推荐
相关产品推荐

