
本文介绍如何在 laravel 中基于原始 sql 查询对每日下载量进行分组聚合后,高效计算累计总和(cumulative sum),并返回包含日期、当日数量及累计值的完整结果集。
本文介绍如何在 laravel 中基于原始 sql 查询对每日下载量进行分组聚合后,高效计算累计总和(cumulative sum),并返回包含日期、当日数量及累计值的完整结果集。
在 Laravel 中,Eloquent 查询构建器本身不直接支持窗口函数(如 SUM() OVER (ORDER BY ...))或变量累加逻辑(尤其在较老 MySQL 版本中),因此对已分组的聚合结果进行累计求和时,纯 Eloquent 方式往往需在 PHP 层遍历处理,效率较低且无法利用数据库能力。更推荐的做法是使用原生 SQL 配合用户变量或窗口函数,在数据库层面完成累计计算,既保证性能,又确保数据一致性。
以下是一个经过优化、兼容 MySQL 5.7+ 的解决方案(使用用户变量模拟累计逻辑):
use Illuminate\Support\Facades\DB; $table = Downloads::getTableName(); $downloads = DB::select(<p>✅ <strong>关键说明:</strong> </p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2877" title="Laravel"><img src="https://img.php.cn/upload/skill/000/000/081/178938495133669.jpg" alt="Laravel" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2877" title="Laravel" class="overflowclass">Laravel</a> <p class="overflowclass">避免常见的Laravel错误:N+1查询、批量赋值、缓存陷阱及队列序列化陷阱。</p> </div> <a rel="nofollow" href="/xiazai/skill2877" title="Laravel" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- DATE(created_at) 替代 DATE_FORMAT(..., '%Y-%m-%d'),语义更清晰且索引友好;
- 子查询 grouped 先完成按日聚合,并显式 ORDER BY date ASC,确保累计顺序正确;
- CROSS JOIN (SELECT @running_total := 0) 初始化变量,避免因会话状态残留导致错误;
- 变量 @running_total 在主 SELECT 中逐行累加,生成 cumm_total_count 字段。
⚠️ 注意事项:
- 此方案依赖 MySQL 用户变量,在 MySQL 8.0+ 中更推荐使用标准窗口函数(如 SUM(total_count) OVER (ORDER BY date)),语法更安全、可读性更强;
- 若需在 Laravel 模型中复用,建议封装为静态方法或 Repository 方法,避免硬编码表名;
- 使用 DB::select() 返回的是 stdClass 对象数组,如需转为 Collection 或模型集合,可调用 collect($downloads) 进行后续处理。
? 进阶建议(MySQL 8.0+):
若环境支持,优先改用现代窗口函数写法,无需变量且符合 SQL 标准:
$downloads = DB::select(<p>该方式语义明确、线程安全、易于维护,是 Laravel 应用对接高版本数据库时的首选实践。</p>










