Laravel使用DB::raw()排序取首条触发SQL语法错误如何解决
报错原因
你遇到的1064语法错误核心是MySQL没有内置FIRST()聚合函数,你在DB::raw()中写的这个函数在MySQL中不被支持,所以直接触发语法报错。
需求实现方案
你的需求是「先按日取最新1条记录,再按月汇总这些记录的event_count值」,可以通过子查询+关联的方式实现,兼容所有主流MySQL版本,Laravel实现代码如下:
// 子查询:先筛选出每一天最新一条记录的创建时间 $dailyLatest = GoogleAnalytics::selectRaw('DATE(created_at) as date, MAX(created_at) as latest_created_at') ->where('event_category', 'Category') ->where('event_action', 'Action') // 替换成你需要的5个月时间区间即可 ->whereBetween('created_at', ['2021-01-01 00:00:00', '2021-05-31 23:59:59']) ->groupByRaw('DATE(created_at)'); // 主查询:关联子查询拿到每日最新记录,再按月聚合求和 $result = GoogleAnalytics::joinSub($dailyLatest, 'daily_latest', function ($join) { $join->on(DB::raw('DATE(google_analytics.created_at)'), '=', 'daily_latest.date') ->on('google_analytics.created_at', '=', 'daily_latest.latest_created_at'); }) ->where('event_category', 'Category') ->where('event_action', 'Action') ->selectRaw('DATE_FORMAT(google_analytics.created_at, "%Y-%m") as created_at, SUM(event_count) as sessions') ->groupByRaw('DATE_FORMAT(google_analytics.created_at, "%Y-%m")') ->orderBy('created_at', 'desc') ->get();
如果你使用的是MySQL 8.0及以上版本,也可以用窗口函数实现,逻辑更清晰:
$result = GoogleAnalytics::fromSub(function ($query) { $query->selectRaw('*, DATE_FORMAT(created_at, "%Y-%m") as month, ROW_NUMBER() OVER (PARTITION BY DATE(created_at) ORDER BY created_at DESC) as rn' ) ->where('event_category', 'Category') ->where('event_action', 'Action') ->whereBetween('created_at', ['2021-01-01 00:00:00', '2021-05-31 23:59:59']); }, 't') ->where('rn', 1) ->selectRaw('month as created_at, SUM(event_count) as sessions') ->groupBy('month') ->orderBy('month', 'desc') ->get();
注意事项
你原代码中的时间筛选条件仅限制了2021-06-08单日数据,若需要返回5个月的聚合结果,需要将时间范围调整为对应5个月的起止时间。
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

