'Laravel group record by months and sum price

Hello i am trying to group record by months and sum price from orders

I tried something like this

       $order = Order::select(DB::raw('sum(price) as sums'))->groupBy(function($date) {
    return Carbon::parse($date->created_at)->format('Y-m');

});

but no luck, I wanna get collection which I could later implement in data-tables?



Solution 1:[1]

Please try with this:

  $orders = Order::select(
            DB::raw('sum(price) as sums'), 
            DB::raw("DATE_FORMAT(created_at,'%M %Y') as months")
  )
  ->groupBy('months')
  ->get();

Solution 2:[2]

As an addition to @Anowar Hossain answer, you may use this solution to further get the index of other months regardless of whether they have values in them or not.

$orders = Order::select(
            DB::raw('sum(price) as sums'), 
            DB::raw("DATE_FORMAT(created_at,'%M %Y') as months"),
            DB::raw("DATE_FORMAT(created_at,'%m') as monthKey")
  )
  ->groupBy('months', 'monthKey')
  ->orderBy('created_at', 'ASC')
  ->get();

If you're looking to provide data for the year only, you can consider doing this instead:

$orders = Order::select(
            DB::raw('sum(price) as sums'), 
            DB::raw("DATE_FORMAT(created_at,'%m') as monthKey")
  )
  ->whereYear('created_at', date('Y'))
  ->groupBy('monthKey')
  ->orderBy('created_at', 'ASC')
  ->get();

Then create an array with 12 zero values like this:

$data = [0,0,0,0,0,0,0,0,0,0,0,0];

foreach($orders as $order){
    $data[$order->monthKey-1] = $order->sums;
}

return $data; // [0,10000,5000,7000,9000,0,0,0,0,15000,0,0]

Hope this helps someone out there!

Solution 3:[3]

Here’s a little more coherent way to do @okafor-t-kosiso’s answer:

$payments = Order::select( 
        \DB::raw('SUM(price) as subtotal'), 
        \DB::raw("EXTRACT(YEAR FROM `created_at`) as year"),
        \DB::raw("EXTRACT(MONTH FROM `created_at`) as month")
      )->whereBetween('created_at', [$start, $end])
      ->groupBy('month', 'year');

Results in something like:

|----------------------|
|subtotal |year |month |
|----------------------|
|234.32   |2022 |2     |
|654.02   |2022 |3     |
|35.00    |null |null  |
|----------------------|

Tested, and this will also actually aggregate on null date columns.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Anowar Hossain
Solution 2 Okafor T Kosiso
Solution 3 Dan S