Laravel中如何统计不同状态的请求数量 有什么更高效的实现方案?
优化方案
原有实现问题
- 嵌套了4个独立子查询,合计执行5次数据库请求,额外增加了数据库IO开销
- 存在大量重复的条件代码,维护成本高
最优实现方案(推荐)
使用条件聚合实现一次查询返回所有状态统计结果,和原有返回结构完全兼容,性能提升4倍以上:
'requests_count' => Request::where('user_id', auth()->id()) ->selectRaw('SUM(CASE WHEN status = "active" THEN 1 ELSE 0 END) as active') ->selectRaw('SUM(CASE WHEN status = "pause" THEN 1 ELSE 0 END) as pause') ->selectRaw('SUM(CASE WHEN status = "pending" THEN 1 ELSE 0 END) as pending') ->selectRaw('SUM(CASE WHEN status = "unapproved" THEN 1 ELSE 0 END) as unapproved') ->first();
如果你的数据库支持IF函数(比如MySQL),可以简化写法:
'requests_count' => Request::where('user_id', auth()->id()) ->selectRaw('SUM(IF(status = "active", 1, 0)) as active') ->selectRaw('SUM(IF(status = "pause", 1, 0)) as pause') ->selectRaw('SUM(IF(status = "pending", 1, 0)) as pending') ->selectRaw('SUM(IF(status = "unapproved", 1, 0)) as unapproved') ->first();
可选灵活实现方案
如果后续可能新增统计的状态,可以用groupBy分组统计的写法,后续新增状态只需要修改结果映射部分即可:
// 一次查询按状态分组统计数量 $statusCounts = Request::where('user_id', auth()->id()) ->selectRaw('status, count(id) as count') ->groupBy('status') ->pluck('count', 'status'); // 补全所有需要的状态,不存在的状态默认返回0 'requests_count' => [ 'active' => $statusCounts->get('active', 0), 'pause' => $statusCounts->get('pause', 0), 'pending' => $statusCounts->get('pending', 0), 'unapproved' => $statusCounts->get('unapproved', 0), ];
额外性能优化建议
给requests表的user_id和status字段添加联合索引,可进一步降低查询耗时,适合数据量超过10万的表场景。
内容的提问来源于stack exchange,提问作者Ghiath Al-Khatib
相关产品推荐
相关产品推荐

