不建议在where或groupby中使用date_format提取当日数据,应改用wheredate或wherebetween;仅在select中用date_format格式化输出,配合set lc_time_names支持中文星期。

在 Laravel 9 的每日数据查询中,DATE_FORMAT 是 MySQL 层的格式化函数,**不建议直接在 where 或 groupBy 条件中使用它来提取“当天”数据**——这会导致索引失效、性能骤降。正确做法是用 Laravel 提供的查询构建器方法(如 whereDate)或原生范围查询,把格式化仅保留在结果展示层。
只用于 SELECT 输出:让日期看起来更友好
当你需要把数据库中的 DATETIME 字段(如 created_at)转成“2024年10月21日”或“10-21 14:30”这类字符串用于报表、导出或 API 返回时,可以用 DATE_FORMAT 配合 selectRaw:
->selectRaw("DATE_FORMAT(created_at, '%Y年%m月%d日') as date_label")->selectRaw("DATE_FORMAT(updated_at, '%m-%d %H:%i') as time_short")- 中文星期需提前设置:
DB::statement("SET lc_time_names = 'zh_CN'");,再用%W(星期全称)或%a(缩写)
别在 WHERE 中用 DATE_FORMAT 筛选“今天”
❌ 错误示范(会丢弃索引):->whereRaw("DATE_FORMAT(created_at, '%Y-%m-%d') = ?", [today()->format('Y-m-d')])
✅ 正确替代(走索引,高效):->whereDate('created_at', today())
或者更精确地(避免隐式类型转换):->whereBetween('created_at', [today()->startOfDay(), today()->endOfDay()])
GROUP BY 按天聚合时,优先用 whereDate + groupBy 字段
要查“每天新增用户数”,不要写:->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
而应确保字段本身是 DATE 类型,或用 Laravel 原生支持的方式:->selectRaw('DATE(created_at) as day, COUNT(*) as count')->groupBy('day')->orderBy('day')
说明:MySQL 的 DATE() 函数比 DATE_FORMAT(..., '%Y-%m-%d') 更轻量,且在某些版本中对索引更友好;更重要的是,Laravel 的 whereDate 和 DATE() 在执行计划中更容易被优化器识别。
配合 Carbon 处理时区与边界,比纯 SQL 更可靠
数据库存的是 UTC?本地时区是 Asia/Shanghai?
直接用 today() 可能跨天出错。推荐显式指定:
$todayCN = Carbon::today('Asia/Shanghai');-
->whereDate('created_at', $todayCN)(前提是字段按本地时区存储) - 若字段为 UTC,应转换:
->whereBetween('created_at', [$todayCN->utc()->startOfDay(), $todayCN->utc()->endOfDay()])
这样比硬写 DATE_FORMAT(created_at, '%Y-%m-%d') 更可控,也避免了 MySQL 服务器时区和应用时区不一致引发的统计偏差。











