Laravel查询构建器实现带MAX子查询的LEFT JOIN的正确方法
问题:Laravel查询构建器实现带关联子查询的LEFT JOIN
原生SQL查询
SELECT * FROM collection_companies cc LEFT JOIN collection_company_links ccl ON cc.id = ccl.collection_company_id AND ccl.id = ( SELECT MAX(id) FROM collection_company_links ccl2 WHERE ccl2.collection_company_id = ccl.collection_company_id )
尝试的Laravel查询构建器代码(存在问题)
$data = DB::table('collection_companies as cc') ->leftJoin('collection_company_links as ccl', 'cc.id', '=', 'ccl.collection_company_id') ->where('ccl.id', function ($query) { $query->select(DB::raw("MAX(id)"))->from('collection_company_links as ccl2') ->where('ccl2.collection_company_id', 'ccl.collection_company_id'); });
问题原因
代码中where('ccl2.collection_company_id', 'ccl.collection_company_id')会把ccl.collection_company_id当作字符串字面量处理,而非关联表的字段引用,导致子查询逻辑失效。
正确实现方式
要匹配原生SQL的逻辑,需要将关联条件全部放在LEFT JOIN的ON子句中,同时用whereColumn方法来比较数据库字段,避免被当作字符串处理。
正确代码如下:
$data = DB::table('collection_companies as cc') ->leftJoin('collection_company_links as ccl', function ($join) { $join->on('cc.id', '=', 'ccl.collection_company_id') ->whereColumn('ccl.id', function ($query) { $query->select(DB::raw('MAX(id)')) ->from('collection_company_links as ccl2') ->whereColumn('ccl2.collection_company_id', 'ccl.collection_company_id'); }); }) ->get();
关键说明
- 使用
leftJoin的闭包形式,把所有关联条件写入ON子句,和原生SQL逻辑完全对齐,避免破坏LEFT JOIN的特性。 - 用
whereColumn替代普通where,专门用来比较两个数据库字段,确保字段引用的正确性。 - 子查询内部同样使用
whereColumn关联字段,保证子查询能正确关联外部表的字段值。
内容的提问来源于stack exchange,提问作者Efratista
相关产品推荐
相关产品推荐

