
本文介绍如何在 laravel 中通过一条 eloquent 查询语句,同时统计多个不同条件下的记录数量,替代多次独立查询,显著提升数据库查询效率与代码可维护性。
本文介绍如何在 laravel 中通过一条 eloquent 查询语句,同时统计多个不同条件下的记录数量,替代多次独立查询,显著提升数据库查询效率与代码可维护性。
在实际开发中,我们常需对同一数据表按不同业务逻辑进行分组统计,例如统计工单系统中的「待处理」「已分配」「未解决」等状态数量。若采用传统方式——分别执行 Ticket::where(...)->count() 四次(如问题所示),不仅会产生 4 次数据库往返,还增加了连接开销与网络延迟。
Laravel 提供了灵活的 selectRaw() 方法,结合 SQL 的 CASE WHEN 表达式,可在单次查询中完成多维度条件计数。以下是优化后的写法:
$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();
执行后,$result 是一个 stdClass 对象,包含四个属性:
- $result->open_tickets:状态为 1 的工单数
- $result->pending_tickets:状态为 2 的工单数
- $result->unassigned_tickets:agent_id 为空的工单数
- $result->unresolved_tickets:状态不为 3 或 4 的工单数
✅ 优势总结:
- ✅ 单次查询,减少 DB 连接与 I/O 开销;
- ✅ 语义清晰,所有逻辑集中于一处,便于复用与测试;
- ✅ 兼容 MySQL、PostgreSQL 等主流数据库(CASE WHEN 为 SQL 标准);
- ✅ 可无缝集成到 Eloquent Scope、API 响应或仪表盘统计模块中。
⚠️ 注意事项:
- 若需兼容软删除模型(SoftDeletes),请确保添加 ->withTrashed() 或 ->withoutTrashed() 显式控制;
- 在高并发场景下,该查询仍属轻量聚合,但若表数据量超千万级,建议为 status 和 agent_id 字段建立联合索引以加速 CASE 判断;
- 避免在 selectRaw 中拼接用户输入,防止 SQL 注入——所有条件值应为硬编码或经 DB::raw() 安全包装的参数化表达式。
通过这一技巧,你不仅能写出更高效、更优雅的 Laravel 代码,也为后续扩展(如增加「今日新建」「超时未响应」等新维度)预留了简洁一致的结构基础。











