Laravel Query Builder左连接丢失行:需保留无匹配行并填充空值
解决Laravel左连接后无匹配行被丢弃的问题
问题出在你对amenity_pricing_reviews表的过滤条件位置上——当前你把whereIn('apr.building_id', $data['building_ids'])和whereNull('apr.deleted_at')放在了全局的where子句里,这会让左连接的效果失效:当apr表没有匹配行时,apr.building_id和apr.deleted_at都是null,不满足这些where条件,所以整行被过滤掉了。
要保留无匹配的行,同时让apr相关字段为null,你需要把这两个条件移到左连接的on子句中,这样只会在关联apr表时筛选符合条件的行,不会影响主表的结果。
修改后的查询代码如下:
$results = DB::table('amenities as a') ->leftJoin('amenity_values as av','av.amenity_id','=','a.id') ->leftJoin('units_amenities_values as uav','uav.amenity_value_id','=','av.id') ->leftJoin('units as u','uav.unit_id','=','u.id') // 把apr的过滤条件移到on子句里 ->leftJoin('amenity_pricing_reviews as apr', function($join) use ($data) { $join->on('apr.unit_id', '=', 'u.id') ->whereIn('apr.building_id', $data['building_ids']) ->whereNull('apr.deleted_at'); }) ->select('a.id as amenity_id','a.amenity_name','a.category_id', 'av.amenity_value','u.id as unit_id','u.unit_number','apr.dom','apr.building_id') ->where('a.property_id', $data['property_id']) ->whereNull('u.deleted_at') ->whereNull('av.deleted_at') ->whereNull('a.deleted_at') ->orderBy('a.amenity_name','asc') ->get() ->groupBy(['category_id','unit_id']);
关键修改说明:
- 将原本的普通
leftJoin改为闭包形式的leftJoin,这样可以在on子句后追加额外的过滤条件 - 把
whereIn('apr.building_id', $data['building_ids'])和whereNull('apr.deleted_at')从全局where移到join的闭包内,确保只有符合条件的apr行才会被关联,没有匹配时则保留null值 - 其他条件和后续的
groupBy逻辑完全保留,确保结果结构和原有业务逻辑兼容
这样修改后,即使amenity_pricing_reviews表中没有匹配的行,主表的所有符合条件的行都会被保留,apr.dom和apr.building_id字段会自动填充为null,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Saroj Shrestha
相关产品推荐
相关产品推荐

