Laravel如何对关联表字段求和并添加至对象后按求和值排序
实现关联表字段求和并按该值排序Inventory对象(Laravel)
这是个很常见的Eloquent关联统计排序需求,我给你几个不同场景下的解决方案,你可以根据自己的Laravel版本和业务需求选择:
方法一:使用Laravel自带的withSum(推荐,Laravel 8+)
如果你的Laravel版本在8及以上,直接用框架提供的withSum方法是最简洁高效的方式,它能直接在数据库层面完成求和与排序:
$inventories = Inventory::withSum('deliveryRecord', 'units') ->orderBy('delivery_record_sum_units', 'desc') // 改成'asc'就是升序排序 ->get();
说明:
withSum('deliveryRecord', 'units'):会自动给每个Inventory对象添加一个delivery_record_sum_units属性,值就是该Inventory关联的所有deliver_record记录中units字段的总和。orderBy('delivery_record_sum_units', 'desc'):直接在数据库查询阶段按求和值排序,相比内存排序性能要好很多,适合数据量较大的场景。
之后你可以直接通过$inventory->delivery_record_sum_units访问这个求和结果,返回的集合已经是排好序的状态。
方法二:手动关联查询(兼容Laravel 8以下版本)
如果你的Laravel版本较低,没有withSum方法,可以用join配合原生SQL来实现:
use Illuminate\Support\Facades\DB; $inventories = Inventory::select('inventory.*', DB::raw('SUM(deliver_record.units) as total_units')) ->leftJoin('deliver_record', 'deliver_record.product_id', '=', 'inventory.id') ->groupBy('inventory.id') ->orderBy('total_units', 'desc') ->get();
说明:
- 通过左连接关联两张表,用
SUM()聚合函数计算units的总和,并给结果起别名total_units。 - 按
total_units字段排序后,每个Inventory对象会携带这个求和属性,用法和方法一类似。
方法三:集合层面排序(适合小数据量场景)
如果已经提前获取了Inventory集合,需要在PHP内存中处理排序,可以用集合的方法来实现:
// 先加载所有Inventory及其关联的deliveryRecord $inventories = Inventory::with('deliveryRecord')->get(); // 计算每个Inventory的units总和并排序 $sortedInventories = $inventories->map(function ($inventory) { // 给Inventory对象添加自定义属性total_units $inventory->total_units = $inventory->deliveryRecord->sum('units'); return $inventory; })->sortByDesc('total_units'); // sortBy是升序
说明:
- 先通过
with('deliveryRecord')预加载关联数据,避免N+1查询问题。 - 用
map遍历集合,给每个Inventory添加求和属性,再用sortByDesc完成排序。 - 这种方式适合数据量不大的情况,数据量大时不推荐,因为会占用更多内存。
额外注意
确保你的Inventory模型中已经正确定义了关联关系:
// Inventory.php 模型文件 public function deliveryRecord() { return $this->hasMany(DeliveryRecord::class, 'product_id'); }
内容的提问来源于stack exchange,提问作者bohdan baida
相关产品推荐
相关产品推荐

