Laravel 8根据两列字段值合并重复行并统计对应数量
问题说明
- 数据表
day_meals包含id、user_id、meal_id、meal_variable_id、date5个字段 - 现有6条测试数据,其中id=3、id=4的两条记录在
meal_id、meal_variable_id、date、user_id字段值完全一致 - 目标需求:查询指定日期的所有记录,按
meal_id和meal_variable_id合并重复行,最终返回5条结果,合并后的重复组需要携带值为2的数量统计字段 - 原有代码问题:两次尝试的
groupBy逻辑仅完成了分组嵌套,未追加数量统计逻辑,返回结构缺少计数字段
实现方案
方案1:数据库层直接分组统计(推荐,性能更好)
直接通过查询构造器在数据库侧完成分组和计数,减少PHP层的数据处理量,代码如下:
$targetDate = date('Y-m-d'); $data = DayMeal::where('date', $targetDate) ->select( 'user_id', 'meal_id', 'meal_variable_id', 'date', \DB::raw('COUNT(id) as meal_count') ) ->groupBy('meal_id', 'meal_variable_id') ->get();
返回结果说明:
- 最终返回5条记录,和预期数量一致
- 每条记录携带
meal_count字段标识该组的记录条数,两条重复记录合并后的分组该字段值为2 - 如果开启了MySQL严格模式,因为同组的
user_id、date值完全一致,该写法不会触发语法报错。
方案2:集合层加工处理
如果已经查询出指定日期的全量记录,可以通过集合方法加工得到需要的结构,代码如下:
$meals_day = DayMeal::where('date', date('Y-m-d'))->get(); $data = $meals_day ->groupBy(fn($item) => $item->meal_id . '_' . $item->meal_variable_id) ->map(function ($group) { $record = $group->first(); $record->meal_count = $group->count(); return $record; }) ->values();
逻辑说明:
- 用闭包拼接两个分组字段的值作为分组key,避免多层数组传参给
groupBy导致的过深嵌套 - 遍历每个分组,取组内第一条记录作为基础数据,追加
meal_count字段赋值为组内总条数 - 最后调用
values()重置集合键名,得到下标连续的5条结果,重复组的计数字段值符合要求。
内容的提问来源于stack exchange,提问作者Hasan Hatem
相关产品推荐
相关产品推荐

