在 laravel 13 中用 eloquent 实现每日销售额分组统计,需用 selectraw('date(paid_at) as date') 和 sum(total_price),配合 wherenotnull('paid_at')、groupby('date') 及时区与索引优化,支持 mysql/postgresql/sqlite 跨库适配,并可补全空日期返回连续数据。

在 Laravel 13 中用 Eloquent 实现每日销售额分组统计,核心是利用 groupBy 配合日期函数(如 DATE() 或 CAST()),并确保数据库字段类型和时区处理正确。
确认订单表结构与时间字段
假设你有一张 orders 表,其中:
-
total_price是 decimal 类型,表示单笔订单金额 -
paid_at是 datetime/timestamp 类型,记录支付完成时间(非created_at,因未支付订单不应计入销售额) - 确保该字段有索引(尤其用于按天查询时能走索引)
基础分组统计写法(MySQL)
使用原生 SQL 函数提取日期部分,并聚合求和:
$dailySales = Order::selectRaw('DATE(paid_at) as date')
->selectRaw('SUM(total_price) as sales')
->whereNotNull('paid_at') // 只统计已支付订单
->groupBy('date')
->orderBy('date', 'desc')
->get();
返回结果中 date 是字符串格式(如 "2025-04-01"),sales 是对应日总销售额。
适配不同数据库的兼容写法
Laravel 的 DB::raw() 在跨数据库时需注意函数差异:
-
PostgreSQL:用
DATE(paid_at)或TO_CHAR(paid_at, 'YYYY-MM-DD'),但 groupBy 要保持一致 -
SQLite:用
DATE(paid_at)即可,支持良好 - 若想统一且安全,可用 Laravel 内置的
toDateString()配合集合处理(适合数据量不大时)
添加时间范围与格式化建议
实际项目中常需限定最近 N 天、或导出为图表所需格式:
$last7Days = Order::selectRaw('DATE(paid_at) as date')
->selectRaw('COALESCE(SUM(total_price), 0) as sales')
->whereBetween('paid_at', [now()->subDays(6)->startOfDay(), now()->endOfDay()])
->whereNotNull('paid_at')
->groupBy('date')
->orderBy('date')
->get()
->keyBy('date'); // 转为以日期为 key 的集合,方便补全空日期
<p>// 补齐缺失日期(如某天无订单则显示 0)
$dates = collect(range(0, 6))
->map(fn($i) => now()->subDays(6 - $i)->toDateString())
->mapWithKeys(fn($date) => [
$date => $last7Days->get($date, (object)['date' => $date, 'sales' => 0])
]);
</p>
这样得到的是连续 7 天的销售数据,含零值,可直接用于前端折线图渲染。











