如何将子查询变量结果传入另一查询?Laravel查询技术咨询
解决方案:将子查询优雅整合到主查询中
当然可以把这个统计子查询整合到主查询里,但不建议用toSql()的方式直接拼接——这样会丢失参数绑定、引发SQL注入风险,而且Laravel Query Builder本身就提供了更优雅安全的做法。
正确的实现方式有两种:
方式1:使用selectSub方法(推荐,可读性更高)
先定义子查询的Query Builder实例,再将其作为字段嵌入主查询:
// 定义子查询:统计每个food_ethic_id对应的chef_food_ethics数量 $subQuery = DB::table('chef_food_ethics') ->selectRaw('count(id) as fCount') ->whereColumn('chef_food_ethics.food_ethic_id', 'food_ethic_managers.food_ethic_id'); // 主查询整合子查询 $r = DB::table('food_ethic_managers') ->where('food_ethic_managers.manager_id', '=', $id) ->leftJoin('staff', 'food_ethic_managers.food_ethic_id', '=', 'staff.id') ->leftJoin('regions', 'staff.region_id', '=', 'regions.id') // 补全你的regions关联逻辑 ->select('food_ethic_managers.*', 'staff.*', 'regions.*') // 选择你需要的字段 ->selectSub($subQuery, 'fCount') // 将子查询结果作为fCount字段返回 ->get();
方式2:直接在select中嵌入原生子查询
如果更习惯于原生SQL的写法,也可以直接把统计逻辑写在selectRaw里:
$r = DB::table('food_ethic_managers') ->where('food_ethic_managers.manager_id', '=', $id) ->leftJoin('staff', 'food_ethic_managers.food_ethic_id', '=', 'staff.id') ->leftJoin('regions', 'staff.region_id', '=', 'regions.id') ->selectRaw(' food_ethic_managers.*, staff.*, regions.*, (SELECT count(id) FROM chef_food_ethics WHERE chef_food_ethics.food_ethic_id = food_ethic_managers.food_ethic_id) as fCount ') ->get();
关键注意点:
- 你原来的子查询中用了
where('chef_food_ethics.food_ethic_id', '=', 'food_ethic_managers.food_ethic_id'),这里要改成whereColumn(或者在原生SQL中直接写字段等式)——因为where会把第二个参数当成字符串值,而不是关联表的字段名,会导致统计结果完全错误。 - 为什么不能用
toSql()拼接?toSql()返回的SQL带有占位符(比如?),但不会附带绑定的参数,直接拼入主查询会引发语法错误,同时存在SQL注入隐患。
内容的提问来源于stack exchange,提问作者Constantine
相关产品推荐
相关产品推荐

