Laravel Eloquent: Finding SUM/COUNT/AVG of each group

Updated: January 18, 2024 By: Guest Contributor Post a comment

Introduction

Laravel Eloquent provides an intuitive and fluent interface for interacting with your database. When working with large datasets, particularly those with grouping requirements, you may often need to perform aggregate functions like SUM, COUNT, and AVG. This tutorial will guide you through using Eloquent to find the sum, count, and average of each group in a Laravel application.

Understanding Aggregations

Aggregate functions perform a calculation on a set of values and return a single value. In the context of a database, these functions can be applied across multiple rows of a table. Some common aggregate functions are:

  • SUM: Adds together all the values in a particular column.
  • COUNT: Counts the number of rows in a table, or the number of non-NULL values in a column.
  • AVG: Calculates the average of all the non-NULL values in a column.

Setting Up the Environment

Make sure you have a Laravel project setup before starting. You should have a table with data to group and aggregate. For demonstration purposes, let’s assume you have a sales table with the following columns: id, date, product_id, quantity, and sale_amount.

Summing a Column with Eloquent

To calculate the total sales amount for each product, you would group by product_id and summation on sale_amount:

$totalSales = Sale::selectRaw('product_id, SUM(sale_amount) as total_sales')
             ->groupBy('product_id')
             ->get();

This Eloquent query maps directly to a SQL query that performs the same function. Key points include the use of selectRaw to allow raw expressions, and groupBy to aggregate data by product.

Counting Rows in a Group

To count the number of sales transactions for each product:

$salesCount = Sale::selectRaw('product_id, COUNT(*) as total_count')
               ->groupBy('product_id')
               ->get();

The COUNT(*) function counts all rows per group determined by the groupBy clause.

Calculating Average with Eloquent

Averaging a column’s values can give insight into the typical value for that group. For example, calculating the average sale amount for each product:

$averageSale = Sale::selectRaw('product_id, AVG(sale_amount) as average_sale')
                 ->groupBy('product_id')
                 ->get();

The AVG function operates on the grouped sale_amount values to produce an average for each product.

Complex Grouping with Joins

Often in a relational database, you’ll need to join tables before you can perform aggregate functions across them. In Laravel Eloquent:

$totalSalesByProduct = Sale::join('products', 'sales.product_id', '=', 'products.id')
                        ->selectRaw('products.name, SUM(sales.sale_amount) as total_sales')
                        ->groupBy('products.name')
                        ->get();

In this case, Eloquent joins the sales and products tables before grouping the rows by product name and summing the sales amounts.

Using Raw Methods with GroupBy

While Eloquent’s selectRaw, groupBy, and aggregate functions cover most needs, sometimes you might need more complex queries. Eloquent’s DB::raw() method lets you inject raw SQL into your queries:

$monthlySales = Sale::select(DB::raw('YEAR(date) as year, MONTH(date) as month, SUM(sale_amount) as total'))
                    ->groupBy(DB::raw('YEAR(date), MONTH(date)'))
                    ->get();

This will return sales totals grouped by year and month, providing a clear picture of monthly sales trends.

Dealing with Group By Restrictions

Some SQL databases, like MySQL in ‘strict’ mode, require that all selected columns be used in the group by statement. In Laravel, handling this can be done by including all grouped columns:

$detailedSales = Sale::select('product_id', DB::raw('YEAR(date) as year, MONTH(date) as month, SUM(sale_amount) as total'))
                    ->groupBy('product_id', DB::raw('YEAR(date), MONTH(date)'))
                    ->get();

Now you’ll get sales data grouped by both product and date. This needs to be done carefully to ensure that your grouping columns uniquely identify each row.

Conclusion

Performing group-specific aggregate calculations such as SUM, COUNT, and AVG using Laravel’s Eloquent can significantly simplify your database interactions. Whether you’re dealing with simple or complex datasets, Eloquent’s expressive syntax allows you to write less code while accomplishing more, maintaining readability and reducing the likelihood of errors. With the techniques outlined in this tutorial, you’re equipped to handle a variety of grouping and aggregation scenarios in your Laravel applications.