Laravel 9中按日期分组查询每日统计数据需用数据库日期函数(如DATE())截断时间字段,配合groupBy()实现;推荐Query Builder方式,Eloquent可用selectRaw;注意跨库函数差异及补零处理。

在 Laravel 9 中按日期分组查询每日统计数据,核心是利用数据库的日期函数(如 DATE()、DATE_FORMAT())配合 Eloquent 或 Query Builder 的 groupBy() 实现。关键在于:确保时间字段被正确截断为“日期”粒度,避免因时间部分不同导致同一天被拆分成多组。
使用 Query Builder 按日期分组(推荐)
适用于需要灵活控制 SQL、或统计字段涉及聚合(如 COUNT、SUM)的场景:
- 用
DB::raw('DATE(created_at)')提取日期部分(MySQL),并别名为date - 在
select()中包含该表达式和聚合函数(如COUNT(*)) - 在
groupBy()中再次使用相同表达式,确保分组逻辑一致
示例(统计每日新增用户数):
$dailyStats = DB::table('users')
->select(
DB::raw('DATE(created_at) as date'),
DB::raw('COUNT(*) as count')
)
->whereBetween('created_at', ['2024-01-01', '2024-12-31'])
->groupBy('date')
->orderBy('date')
->get();
使用 Eloquent 模型 + selectRaw
若你习惯用模型操作,也可在 Eloquent 中实现,语义更清晰:
- 调用
selectRaw()替代原生select(),支持 SQL 表达式 - 注意:Eloquent 默认会添加主键等字段,建议显式指定所需字段,避免干扰分组
- 分组字段必须出现在
selectRaw中,且groupBy()参数需与之完全一致(如用别名date,则写groupBy('date'))
示例:
$stats = User::selectRaw('DATE(created_at) as date, COUNT(*) as count')
->whereDate('created_at', '>=', '2024-01-01')
->groupBy('date')
->orderBy('date')
->get();
适配不同数据库的日期函数
Laravel 不自动跨库转换日期函数,需根据实际数据库调整:
-
MySQL:用
DATE(created_at)或DATE_FORMAT(created_at, "%Y-%m-%d") -
PostgreSQL:用
DATE(created_at)或created_at::date -
SQLite:用
DATE(created_at) - 若项目需多库兼容,可封装成作用域或辅助方法,运行时判断连接驱动
补充技巧:补全无数据的日期(如显示 7 天内每日数据,含 0)
数据库分组只返回有记录的日期,若需补零,建议在 PHP 层处理:
- 先查出有数据的日期结果,转为以日期为 key 的集合(如
collect($stats)->keyBy('date')) - 用
CarbonPeriod生成目标日期范围数组 - 遍历该范围,从集合中取值,不存在则默认为 0
例如生成最近 7 天完整统计:
$range = CarbonPeriod::create(now()->subDays(6), '1 day', now());
$statsMap = collect($stats)->keyBy('date');
$result = $range->map(function ($date) use ($statsMap) {
$item = $statsMap->get($date->format('Y-m-d'), (object)['date' => $date->format('Y-m-d'), 'count' => 0]);
return $item;
})->values();


















