Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Querying sum of multiple aggregate columns (without groupBy)

I have a transactions table and I’m trying to get the total of each type.

To simply put it looks like this

id type credit_movement
1 top_up 10000
2 fee -50
3 deduct -1000

I am trying to get sum of each type to show as a report.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

top_up: 10000
fee: 50
deduct: 1000
net_expense: 9850 [top_up - deduct - fee]
$types = [
   'top_up' => ['top_up'],
   'deduct' => ['deduct'],
   'fee' => ['fee'],
   'net_expense' => ['top_up', 'deduct', 'fee'], 
];

$query = DB::table('transactions');

foreach ($types as $type => $fields) {

    $query->selectSub(function ($query) use ($fields) {
        return $query->selectRaw('SUM(credit_movement)')->whereIn('type', $fields);
    }, $type);

};

$results = $query->get();

When I do this, I get:

1140 In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column ‘project.transactions.type’; this is incompatible with sql_mode=only_full_group_by..

When I change my database.mysql.strict = false, it works; however I want to make it work properly without needing to change the mysql config.

As of my understanding, this error indicates that I am only selecting aggregated columns, but in my case I don’t actually want to groupBy() anything as this is just reports.

If I try to groupBy('type') it returns everything grouped by type, but the queries are only run within that group.

{
 0: {
    top_up: 10000,
    deduct: 0,
    fee: 0,
    net_expense: 10000
 }
 1: {
    top_up: 0,
    deduct: -1000,
    fee: 0,
    net_expense: -1000
 },
 // etc...
}

Is there a way to obtain without changing strict to false?

{
 0 => {
    top_up: 10000,
    deduct: -1000,
    fee: -50,
    net_expense: 9850
 }
}

>Solution :

The problem with your approach is in the final column that is the sum of the other 3 so you can’t use SUM because you don’t have a column to group.
You could use a subquery but I think that the best solution is to add a little elaboration of the raw data that you get from a simpler query.

$query = DB::table('transactions')
  ->selectRaw('type, SUM(credit_movement) AS movements')
  ->groupBy('type');

$results = array_reduce($query->get(), function(array $res, array $value){
    $res[$array['type']] = $array['movements'];
    return $res;
}, []);

$results['net_expense'] = array_sum($results); 
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading