如何使用Eloquent实现给定原生SQL的子查询写法
Eloquent ORM 实现方案
以下两种写法生成的SQL与你提供的原生语句逻辑完全一致,可根据项目使用的Laravel版本选择。
前置说明
- 需提前创建对应模型:
Client对应clients表,ClientsSummaryData对应clients_summary_data表 - 若
Client模型引入了SoftDeletes软删trait,框架会自动追加where deleted_at is null条件,无需手动编写
推荐写法(Laravel 6+ 通用,返回Eloquent模型集合)
该写法无需额外定义模型关联,直接通过selectSub拼接SELECT子句中的子查询,返回结果字段名与原生SQL完全对齐:
// 构建统计last_buy最大值的子查询 $lastBuySub = ClientsSummaryData::selectRaw('max(last_buy)') ->whereColumn('client_id', 'clients.id'); // 主查询 $clients = Client::select('id', 'sap_id') ->selectSub($lastBuySub, 'last_buy') // 未启用软删时需要手动加下这行,启用软删可省略 ->whereNull('deleted_at') ->get();
如果你的项目是Laravel 8及以上版本,也可以通过关联聚合的withMax方法实现,代码更简洁:
- 先在
Client模型中定义一对多关联
// app/Models/Client.php public function summaryData() { return $this->hasMany(ClientsSummaryData::class, 'client_id'); }
- 直接调用聚合方法查询
$clients = Client::select('id', 'sap_id') ->withMax('summaryData', 'last_buy') ->get();
注意:
withMax返回的结果中,最大值会存储在summary_data_max_last_buy动态属性上,若需要字段名直接为last_buy,请使用上面的selectSub写法。
原生查询构造器写法(无模型依赖)
如果不需要返回Eloquent模型实例,可以直接用查询构造器实现,兼容所有Laravel版本:
$lastBuySub = \DB::table('clients_summary_data as csd') ->selectRaw('max(csd.last_buy)') ->whereColumn('csd.client_id', 'c.id'); $clients = \DB::table('clients as c') ->select('c.id', 'c.sap_id') ->selectSub($lastBuySub, 'last_buy') ->whereNull('c.deleted_at') ->get();
内容的提问来源于stack exchange,提问作者Matheus Inacio
相关产品推荐
相关产品推荐

