查询多个聚合列的总和(不带groupBy)

Posted

技术标签:

【中文标题】查询多个聚合列的总和(不带groupBy)【英文标题】:Querying sum of multiple aggregate columns (without groupBy) 【发布时间】:2022-01-01 06:55:12 【问题描述】:

我有一个transactions 表,我正在尝试获取每种类型的总数。

简单来说就是这个样子

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

我正在尝试获取每种类型的总和以显示为报告。

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();

当我这样做时,我得到:

1140 在没有 GROUP BY 的聚合查询中,SELECT 列表的表达式 #1 包含非聚合列“project.transactions.type”;这与 sql_mode=only_full_group_by 不兼容..

当我更改我的database.mysql.strict = false 时,它可以工作;但是我想让它正常工作而无需更改 mysql 配置。

据我了解,此错误表明我只选择聚合列,但在我的情况下,我实际上不想groupBy() 任何东西,因为这只是报告。

如果我尝试groupBy('type'),它会返回按类型分组的所有内容,但查询仅在该组内运行。


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


有没有办法在不将strict改为false的情况下获取?


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

【问题讨论】:

如果您的 where 子句将结果限制为始终只有一种类型;不要在您的...选择语句中选择类型...您已经知道该值,因为您受到它的限制;所以你不需要选择它,然后你就不需要按它分组。我不知道为什么您不会一次访问数据库就获取所有值/结果并迭代结果而不是执行多个查询;但那是你的设计。严格的 SQL 要求所有非聚合列出现在 group by 中。所以干脆不要选择它。这是有效的,因为您已经从 where 子句中知道了它的值。 您是否尝试添加 ->select('type') ..... 然后 groupBy('type');只需在 select 和 groupBy 中添加类型 @xQbert Laravel 的 selectSub() 不会执行多个查询,这就是我选择它的原因。当我有 +1m 记录时,我宁愿不将所有这些都保存在一个变量中并在运行时计算。这就是为什么我宁愿让mysql计算总和并直接返回结果。 @senty 从纯 SQL 的角度来看:Select type, sum(Credit_movement) x from transactions group by type 为您提供所有类型:但如果您正在迭代它们,那么您不需要类型。 Select sum(credit_Movement) x from transactions where type = 'fee' 或全部获取 SELECT type, sum(credit_movement) x from transactions where type in ('your list') group by type 然后在本地迭代类型,因为您获取所需的数据不多也不少,数据库完成了所有数学运算。 @senty 干杯.. 一切都是为了互相帮助。祝你好运!和......正如你所猜测的;我很讨厌 Laravel。 【参考方案1】:

如果我理解正确,这可能很容易,但我可能没有理解正确。

$result = DB::table('transactions')->selectRaw('type, SUM(credit_movement) as sum')->groupBy('status')->get();

这应该返回如下内容:

type sum
fee -5656
topup 8758
deduct -7625

对于总金额,您可以在 php 中完成,这会更容易

$net = $result->sum('sum'); // equals -5656+8758-7625

希望这会有所帮助,如果我错了,请告诉我。

【讨论】:

是的,这是一个很好的解决方案。谢谢【参考方案2】:

您的方法的问题在于最后一列是其他 3 列的总和,因此您不能使用 SUM,因为您没有要分组的列。 您可以使用子查询,但我认为最好的解决方案是对从更简单的查询中获得的原始数据进行一些详细说明。

$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); 

【讨论】:

谢谢。在这种情况下,您甚至不需要添加selectSub(),您可以直接链接到查询本身。我会采用这个解决方案 - 再次感谢 是的,对不起,我真的从未使用过 laravel 查询生成器,所以我只是复制了你的一些代码......我自己更像一个教条人

以上是关于查询多个聚合列的总和(不带groupBy)的主要内容,如果未能解决你的问题,请参考以下文章

聚合函数和分组查询(有宝藏)

如何划分两个聚合总和数据框

SQL语句的补充

使用多个 WHERE 子句和 GROUP BY 销售人员访问 SQL、聚合总和

pandas编写自定义函数计算多个数据列的加和(sum)使用groupby函数和apply函数聚合计算分组内多个数据列的加和

通过 group by 和 joins 获取多个表的多个列的总和