我有一个名为gk
的表,我目前正在运行两个查询。请查看查询:
Gk::groupBy(DB::raw("MONTH(created_at)"))
->groupBy(DB::raw("YEAR(created_at)"))
->selectRaw('id, user_id, sum(ton) as ton,pl, count(id) as total, sum(w) , created_at')
->with(array('user'=> function($q){
$q->select('id', 'userName', 'profilePic');
}))
->where('user_id', $userData[0]->id)
->get();
此查询返回每个月的一些摘要。你可以看到我按月和年分组结果。我有另一个查询将返回任何给定月份的所有行。 我正在运行这样的第二个查询
$m=Carbon::parse($request->date);
Gk::where('user_id',$request->user_id)->whereRaw(DB::raw("YEAR(created_at)=$m->year"))->whereRaw(DB::raw("MONTH(created_at)=$m->month"))
->orderBy('created_at','desc')
->get();
第二个查询返回任何月份的所有行。我正在foreach循环中为第一个查询中返回的所有月份执行此查询。
我正在尝试将这两个查询合并为一个,以便我可以按月和年获得一组结果以及该月的所有详细信息。
任何帮助,建议或想法都会非常有帮助。
[注意:对于第二个查询中的日期,此日期是created_at
来自第一个查询的结果。]
谢谢。
答案 0 :(得分:1)
我阅读您的问题的方式如下:第二个查询在循环中执行,其结果来自第一个查询。是对的吗?在我的回答中,我已经解释了一种只执行第二次查询而不是循环的方法。你仍然需要执行一次第一次查询。
所以,我认为你最好使用Php收集方法:
$results = Gk::where('user_id',$request->user_id)
->orderBy('created_at','desc')
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
groupBy
方法必须返回要对其进行分组的属性。对于这个例子,我认为使用yyyy-mm
格式会很好。
参考:https://laravel.com/docs/5.5/collections#method-groupby
编辑:也许你也可以摆脱orderBy方法调用,因为你之后进行分组:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
编辑2:要合并两个查询的信息,您可以执行以下操作:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
})->map(function(Collection $rows) {
return [
'sum(ton)' => $rows->sum('ton'),
'total' => $rows->count(),
'sum(w)' => $rows->sum('w'),
'rows' => $rows
];
);
请注意,我在第一个查询中省略了一些选定的列,因为它们在给定的组中不是唯一的。但随意在地图功能中添加任何逻辑。由于我们在map()
之后使用groupBy
,因此map()
的每次调用都会收到一个月的项目集合。您可以使用这个神奇的集合魔法来计算您需要的所有值,并将查询数量减少到只有一个。