Laravel按name字段分组查询name和date两个不同值字段报错如何解决
错误原因说明
- 第一个报错:你在调用
get()之后得到的是Illuminate\Database\Eloquent\Collection集合实例,只有查询构造器才有select方法,集合不存在该方法,所以调用失败。 - 第二个报错:你的MySQL开启了
only_full_group_by模式,该模式要求SELECT子句里的所有非聚合字段,必须都出现在GROUP BY子句中。你仅按name分组,但是SELECT了未聚合的date字段,不符合SQL模式要求,因此抛出语法错误。
正确实现方案
你要实现按name分组、每个name对应多个date的需求,推荐两种常用实现方式:
方案1:使用Laravel集合分组(更灵活)
先查询所有符合条件的记录,再用集合的groupBy方法做后续处理,不需要修改SQL模式,适配性更强:
public function period(Request $req) { // 查询符合日期范围的所有姓名、日期记录 $absences = Absence::whereBetween('date', [$req->from, $req->to]) ->select('name', 'date') ->get(); // 按name分组,统计每个name的缺勤次数和对应的所有日期 $daily = $absences->groupBy('name')->map(function ($item) { return [ 'counts' => $item->count(), 'dates' => $item->pluck('date')->unique() // 可加unique去重相同日期 ]; }); $arr = [ 'absences' => $absences, 'daily' => $daily, 'from' => $req->from, 'to' => $req->to ]; // 注意原代码连续写了两个return,第一个return后后续代码不会执行,按需保留一个即可 // return $arr; return view('period', $arr); }
方案2:直接用SQL聚合查询
如果希望直接通过SQL拿到分组结果,可以用GROUP_CONCAT聚合date字段,符合only_full_group_by的规则:
public function period(Request $req) { // 直接按name分组,聚合统计次数和所有日期 $daily = Absence::whereBetween('date', [$req->from, $req->to]) ->selectRaw('name, COUNT(date) as counts, GROUP_CONCAT(DISTINCT date SEPARATOR ",") as dates') ->groupBy('name') ->get(); // 如需所有原始缺勤记录可单独查询 $absences = Absence::whereBetween('date', [$req->from, $req->to])->get(); $arr = [ 'absences' => $absences, 'daily' => $daily, 'from' => $req->from, 'to' => $req->to ]; return view('period', $arr); }
额外注意事项
原代码中连续写了两个return语句,第一个return $arr执行后,后续的视图返回逻辑永远不会触发,记得根据需求删除不需要的return。
内容的提问来源于stack exchange,提问作者Sermed mayi
相关产品推荐
相关产品推荐

