Laravel关联表group by后按条件求和,B类质量统计失效如何解决
问题原因
- 首先SQL查询不符合规范:你在
paper_stock模型查询时仅按paper_id做group by,在MySQL默认开启ONLY_FULL_GROUP_BY模式的场景下,只会返回每个paper_id对应的第一条paper_stock记录,关联加载的paperstocks数据不完整,你看到的A等级统计正常只是刚好命中了第一条记录里的A等级数据,B等级对应数据没有被加载所以统计不生效。 - 其次模板层统计逻辑不合理:在Blade中反复对关联集合做过滤、求和操作,性能差且容易因为数据不完整出现统计错误。
- 最后可能存在匹配规则问题:Laravel集合的
where方法默认是严格类型匹配,如果你的quality字段存储的B值带空格、大小写不匹配,也会导致匹配失败统计结果为0。
解决方案
推荐直接在查询阶段完成统计,避免模板层处理逻辑,性能更高也更稳定:
1. 修改Livewire Component查询代码
使用Laravel提供的withSum关联条件统计方法:
$this->dry = paper_stock::query() ->with('paper') // 预统计不同质量等级的库存总和 ->withSum([ 'paperstocks as quality_a_total' => fn($q) => $q->where('quality', 'A'), 'paperstocks as quality_b_total' => fn($q) => $q->where('quality', 'B') ], 'qty') ->groupBy('paper_id') // 补充所有需要查询的非聚合字段到groupBy,符合SQL规范,按需补充你用到的字段 ->selectRaw('paper_id, id') ->get();
2. 简化Blade模板代码
移除所有模板内的PHP逻辑,直接读取统计结果即可:
@foreach ($dry as $item) <tr> <td>{{ $item->quality_a_total ?? 0 }}</td> <td>{{ $item->quality_b_total ?? 0 }}</td> </tr> @endforeach
临时兼容方案
如果要保留原有写法,先做两个排查:
- 打印
$item->paperstocks集合,确认其中存在quality为B的记录 - 把集合过滤改为宽松匹配,兼容大小写和空格问题:
$qualityB = $item->paperstocks->filter(function($record) { return strtoupper(trim($record->quality)) === 'B'; })->sum('qty');
内容的提问来源于stack exchange,提问作者Madushan Serasinghe
相关产品推荐
相关产品推荐

