我有一个名为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循环中执行这个查询,用于第一个查询返回的所有月份。
我正在尝试将这两个查询合并为一个查询,以便可以按月份和年份获取一组结果,以及该月份的所有详细信息。
任何帮助、建议或想法都会非常有帮助。
[注意:对于第二个查询中的日期,此日期是第一个查询的结果。]
谢谢您。

最佳答案

我阅读您的问题的方式如下:第二个查询在循环中执行,结果来自第一个查询。对吗在我的回答中,我解释了一种只执行一次而不是在循环中执行第二个查询的方法。您仍然需要执行第一个查询一次。
因此,我认为您最好使用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函数中添加任何逻辑。因为我们在map()之后使用groupBy,所以每次调用map()都会收到一个月的项目集合。您可以使用这个神奇的集合来计算您需要的所有值,并将查询数减少到一个。

10-07 16:03
查看更多