Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

floflo's avatar

Sum over multiple column in hasMany relation table

Hi all,

I have a Number Model with hasMany AggregateStatistic relation. AggregateStatistic table has three column ('date','total_bids', 'total_calls');

I'm trying to get all rows from Number model and summing total_bids and total_calls from AggregateStatistic table in Eloquent.

Something like :

App\Number::with('aggregate_statistics')->sum('total_bids','total_calls');

If anyone has an idea , much appreciate.

0 likes
7 replies
lanatel's avatar

Which column is a foreign key on the AggregateStatistic model?

floflo's avatar

number_id, the 4th column, is the foreign key in AggregateStatistic table.

lostdreamer_nl's avatar

You can do the following: (assuming you have the relationship in the number model setup and its method is named aggregateStatistics() )

// Number model:  add these methods:
// this will give the number model a total_bids attribute, which will be the sum of its statistics
public function getTotalBidsAttribute() 
{
    return $this->aggregateStatistics->sum('total_bids');
}

// this will give the number model a total_calls attribute, which will be the sum of its statistics
public function getTotalCallsAttribute() 
{
    return $this->aggregateStatistics->sum('total_calls');
}

// this will give the number model a totals attribute, which will be the sum of both total_calls and total_bids

public function getTotalsAttribute() 
{
    return $this->total_calls + $this->total_bids;
}

Route:

$numbers = App\Number::with('aggregate_statistics')->get();
$totalBids = $numbers->sum('total_bids');
$totalCalls = $numbers->sum('total_calls');
$totals = $number->sum('totals');

dd($totalBids, $totalCalls, $totals);

more info about accessors / mutators: https://laravel.com/docs/5.6/eloquent-mutators

ps. I've had problems before with relationships with capitalization in the name where the caching mechanism did not work properly and would still do n+1 queries even with eager loading..... Keep an eye on your query count :)

1 like
lanatel's avatar
lanatel
Best Answer
Level 2

Than you can do something like that:

Number::leftJoin(DB::raw('(SELECT number_id, SUM(total_bids) as binds_sum, SUM(total_calls) as calls_sum FROM AggregateStatisticTableName GROUP BY number_id) AS statistics'), function ($join) {
            $join->on('statistics.number_id', '=', 'numbers.id');
        })->get();

It does not use your relationship but make just one query

1 like
floflo's avatar

@lanatel

But if I have a division attribute based (in the Model)

public function getPercentAttribute() 
{
    return $this->total_calls/$this->total_bids;
}

How should I call this property, for sum it was easy.

lanatel's avatar

@floflo where do you want to call it? If you need to use it with your sum result than you can do it in the same query

Number::leftJoin(DB::raw('(SELECT number_id, SUM(total_bids) as binds_sum, SUM(total_calls) as calls_sum FROM AggregateStatisticTableName GROUP BY number_id) AS statistics'), function ($join) {
            $join->on('statistics.number_id', '=', 'numbers.id');
        })
    ->select('binds_sum', 'calls_sum ', DB::raw('calls_sum / binds_sum as percent'), 'numbers.id')
    ->get();

Please or to participate in this conversation.