Courses

Laravel GroupBy: Practical Examples

Example 4. GROUP BY Multiple Tables

This example will show you how to group by a column from a different table. For instance, we will display the total amount paid for each user along with how many products they have ordered:

Controller

use App\Models\Order;
use Illuminate\Support\Facades\DB;
 
// ...
 
$orders = Order::selectRaw(
'users.name as user_name, sum(orders.total) as order_total, sum(order_p.total) as total_products'
)
->join('users', 'orders.user_id', '=', 'users.id')
->join(
DB::raw('(select order_id, count(*) as total
from `order_product`
group by order_id) as order_p'),
'order_p.order_id', '=', 'orders.id',
)
->groupBy('user_name')
->get();
 
return view('examples.groupByRelatedColumnEloquent', [
'orders' => $orders
]);

This produces the following SQL query:

select users.name as user_name,
sum(orders.total) as order_total,
sum(order_p.total) as total_products
from `orders`
inner join `users` on `orders`.`user_id` = `users`.`id`
inner join (select order_id, count(*) as total
from `order_product`
group by order_id) as order_p on `order_p`.`order_id` = `orders`.`id`
group by `user_name`

Then in our view, we can display the order_total and total_products columns:

View

{{-- ... --}}
<table class="table-auto w-full">
<thead>
<tr>
<th class="px-4 py-2">User</th>
<th class="px-4 py-2">Total</th>
<th class="px-4 py-2">Total Items</th>
</tr>
</thead>
<tbody>
@foreach ($orders as $order)
<tr>
<td class="border px-4 py-2">{{ $order->user_name }}</td>
<td class="border px-4 py-2">${{ number_format($order->order_total / 100, 2) }}</td>
<td class="border px-4 py-2">{{ $order->total_products }}</td>
</tr>
@endforeach
</tbody>
</table>
{{-- ... --}}

You can find the Automated test example for this lesson in our repository

Previous: Example 3. GROUP BY with Extra Calculations
avatar

In the query, you count the number of purchased unique products. Obviously, if you are trying to calculate the total number of purchased products, then you need to sum up the quantity and make a left join.

$orders = DB::table('orders')
    ->selectRaw(
        'users.name as user_name, sum(orders.total) as total, sum(order_product.quantity) as total_products'
    )
    ->join('users', 'orders.user_id', '=', 'users.id')
    ->join('order_product', 'order_product.order_id', '=', 'orders.id', 'left')
    ->groupBy('user_name')
    ->get();
👍 1
avatar

You are right! These are 2 different statistics you might encounter. In one case, you care about the unique product count, while in other case - you care about the actual SKUs amount (not unique products) :)

For our goal it was just unique products, but in real life - you do see a variaty of calculations

avatar

Hi, I have updated the lesson and added an automated test with our repository link. This should solve the issue that we had here.

avatar
You can use Markdown
avatar
You can use Markdown