
在 laravel 中,可通过 selectraw() 结合 sql case when 实现一次数据库查询完成多个条件计数,显著减少查询次数、提升性能。
在 laravel 中,可通过 selectraw() 结合 sql case when 实现一次数据库查询完成多个条件计数,显著减少查询次数、提升性能。
在处理统计类需求(如工单状态汇总)时,频繁调用多次 count() 会导致 N+1 查询问题——你当前的四次独立查询会向数据库发送四次请求,不仅增加网络开销,还可能成为性能瓶颈。Laravel 支持通过原生 SQL 表达式在单次查询中完成所有条件计数,核心是利用 COUNT(CASE WHEN ... THEN 1 END) 模式。
以下是优化后的单查询写法:
$result = Ticket::selectRaw('COUNT(CASE WHEN status = 1 THEN 1 END) AS open_tickets')
->selectRaw('COUNT(CASE WHEN status = 2 THEN 1 END) AS pending_tickets')
->selectRaw('COUNT(CASE WHEN agent_id IS NULL THEN 1 END) AS unassigned_tickets')
->selectRaw('COUNT(CASE WHEN status NOT IN (3,4) THEN 1 END) AS unresolved_tickets')
->first();
// 获取结果
echo $result->open_tickets; // 开启工单数
echo $result->pending_tickets; // 待处理工单数
echo $result->unassigned_tickets; // 未分配工单数
echo $result->unresolved_tickets; // 未解决工单数(状态非3/4)
✅ 优势说明:
- 仅执行 1 次 SQL 查询,避免重复全表扫描(若无合适索引,多次 count() 可能各自触发完整扫描);
- 返回结果为单个 stdClass 对象,结构清晰、易于解构;
- 兼容 Eloquent 模型作用域、全局作用域及连接约束(如 where('team_id', $id) 可链式添加)。
⚠️ 注意事项:
- CASE WHEN 中的 THEN 1 是关键:COUNT() 仅统计非 NULL 值,ELSE 隐式为 NULL,因此无需显式写 ELSE NULL;
- 若需兼容空数据集,->first() 在无记录时返回 null,建议增加判空处理;
- 复杂条件(如关联字段、JSON 查询)仍可嵌入 CASE 表达式,但需注意数据库方言支持(MySQL/PostgreSQL 均完全支持上述语法);
- 如需进一步聚合(如按日期分组),可配合 groupBy() 扩展,但本例为全表统计,故无需分组。
该方案是 Laravel 性能优化中的经典实践,适用于仪表盘统计、后台报表等高频多维度计数场景。











