You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel/Eloquent如何从同一列返回两个日期范围的求和结果

解决Laravel Eloquent同一SKU多时间段采购总量统计问题

错误分析

你的写法存在两个核心问题:

  1. 多次调用selectRaw会覆盖之前定义的查询字段,最终只会保留最后一个selectRaw的结果;
  2. 多次whereBetween会让查询条件取交集,相当于要求记录同时满足7天和30天的时间范围,这显然不符合需求。

正确实现方案

要在同一查询中统计同一SKU在两个时间段的采购总量,需要用条件聚合(SUM搭配CASE WHEN)来实现,同时用Carbon快速计算时间范围(Laravel默认集成Carbon)。

代码示例(假设Date字段为日期类型)

use Carbon\Carbon;

// 计算时间边界:取当前时间的0点和23:59:59
$todayEnd = Carbon::now()->endOfDay();
$sevenDaysAgo = Carbon::now()->subDays(7)->startOfDay();
$thirtyDaysAgo = Carbon::now()->subDays(30)->startOfDay();

$skuStats = Orders::groupBy('SKU')
    ->selectRaw('
        SKU,
        SUM(CASE WHEN `Date` BETWEEN ? AND ? THEN Quantity ELSE 0 END) as total_last_7_days,
        SUM(CASE WHEN `Date` BETWEEN ? AND ? THEN Quantity ELSE 0 END) as total_last_30_days
    ', [$sevenDaysAgo, $todayEnd, $thirtyDaysAgo, $todayEnd])
    ->get();

针对字符串格式日期的适配(如示例中的07-23-2022)

如果你的Date字段是字符串类型(月-日-年格式),需要先转换为数据库可识别的日期格式(以MySQL为例,用STR_TO_DATE函数):

$skuStats = Orders::groupBy('SKU')
    ->selectRaw('
        SKU,
        SUM(CASE WHEN STR_TO_DATE(`Date`, "%m-%d-%Y") BETWEEN ? AND ? THEN Quantity ELSE 0 END) as total_last_7_days,
        SUM(CASE WHEN STR_TO_DATE(`Date`, "%m-%d-%Y") BETWEEN ? AND ? THEN Quantity ELSE 0 END) as total_last_30_days
    ', [$sevenDaysAgo, $todayEnd, $thirtyDaysAgo, $todayEnd])
    ->get();

关键说明

  • 条件聚合通过CASE WHEN判断每条记录是否属于目标时间段,符合条件则累加Quantity,否则加0;
  • 使用参数绑定(?)避免SQL注入,同时让Laravel自动处理日期格式转换;
  • groupBy('SKU')确保每个SKU只返回一行数据,包含两个时间段的统计结果。

推荐搜索关键词

  • Laravel Eloquent 条件聚合 sum case when
  • Laravel 同一查询多时间段统计
  • Eloquent group by 多维度统计

内容的提问来源于stack exchange,提问作者David-Dj Bryant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:06:29