
本文介绍在 laravel eloquent 中按日期分组时,如何准确获取每组中 datetime 最新的那条完整记录(而非用 max() 等聚合函数误取字段极值),避免单位、数值等字段错配。
本文介绍在 laravel eloquent 中按日期分组时,如何准确获取每组中 datetime 最新的那条完整记录(而非用 max() 等聚合函数误取字段极值),避免单位、数值等字段错配。
在处理生物指标(如体重、血压)等时间序列数据时,一个常见需求是:对每个自然日(date(datetime))只取该日内最后录入的一条记录,以确保 amount(数值)与 unit(单位)来自同一原始记录。你原代码中使用 max(amount) 和 max(unit) 存在严重逻辑缺陷——max() 是独立对各字段取最大值,可能导致返回“今日最高体重值”和“今日最大单位字符串”(如 'kg' vs 'lbs')的错误组合,完全失去数据一致性。
正确做法不是聚合字段,而是先筛选、再分组、最后取每组内 datetime 最大的那条完整记录。但需注意:Eloquent 的 groupBy + latest() 不能直接链式调用生效(latest() 作用于整个结果集,而非每个分组)。因此,推荐以下两种稳健方案:
✅ 方案一:使用窗口函数(Laravel 9+ / MySQL 8.0+ 推荐)
use Illuminate\Support\Facades\DB;
$records = DB::table('records')
->where('user', $uid)
->where('type', 'biometric')
->where('fk', $bid)
->whereBetween(DB::raw('DATE(datetime)'), [$range->min->format('Y-m-d'), $range->max->format('Y-m-d')])
->select(
'id',
'amount as damount',
'unit',
DB::raw('DATE(datetime) as datee')
)
->selectRaw('ROW_NUMBER() OVER (PARTITION BY DATE(datetime) ORDER BY datetime DESC) as rn')
->havingRaw('rn = 1')
->get()
->map(function ($row) {
unset($row->rn);
return $row;
});此方案利用 ROW_NUMBER() 为每日记录按时间倒序编号,再过滤出每组 rn = 1 的记录,保证 damount 与 unit 来自同一条原始数据。
✅ 方案二:子查询关联(兼容旧版 Laravel/MySQL)
$sub = Records::selectRaw('DATE(datetime) as date_day, MAX(datetime) as latest_dt')
->where('user', $uid)
->where('type', 'biometric')
->where('fk', $bid)
->whereBetween('datetime', [$range->min, $range->max])
->groupBy('date_day');
$records = Records::select('amount as damount', 'unit', DB::raw('DATE(datetime) as datee'))
->joinSub($sub, 'latest', function ($join) {
$join->on('records.datetime', '=', 'latest.latest_dt')
->on('records.user', '=', DB::raw($uid))
->on('records.fk', '=', DB::raw($bid));
})
->where('records.type', 'biometric')
->orderBy('datee', 'desc')
->get();⚠️ 注意事项
- 原答案中 ->groupBy("datetime")->latest()->get() 不正确:groupBy("datetime") 按精确时间分组(秒级),无法实现“按天分组”;且 latest() 在分组后失效,实际返回的是全量记录中时间最新的几条,而非每日最新。
- whereBetween(DB::raw("DATE('datetime')"), ...) 写法有误(单引号导致字段名被当字符串),应为 DB::raw('DATE(datetime)')。
- 务必为 datetime 字段添加数据库索引(如 INDEX(datetime)),大幅提升查询性能。
通过上述任一方案,你将获得真正符合业务逻辑的每日最新生物指标记录,确保图表数据准确、可信赖。


















