将不同的 select 求和查询与来自相同 table 的不同位置相结合(Laravel 方式)

Combining different select sum queries with different where from same table (Laravel way)

我有稍微不同的 select 查询来从相同的 table 读取数据。

select user_id
     , SUM(credit_movement) as testing_fees
  from transactions
 where `type` in ('Testing', 'Testing Data') 
   and `user_id` in (118,124,352 ...)
group by `user_id`
select user_id, SUM(credit_movement) as production_fees 
from `transactions` 
where `type` in ('Production', 'Production Data') and `user_id` in (152,521,1341, ...)
group by `user_id`

typeuser_id 正在改变。

在 Laravel 中,我最终对每种类型使用了 1 个查询,但有 10 种类型,这意味着 10 个数据库连接 - 这并不好。

$values['testing_fees'] = \DB::table("transactions")
     ->select(\DB::raw("user_id, SUM(credit_movement) as testing_fees"))
     ->whereIn('type', ["Testing", "Testing Data"])
     ->whereIn('user_id', $userIdsToBeUsed)
     ->whereDate('created_at', '>=', $fromDate->toDateString())
     ->whereDate('created_at', '<=', $toDate->toDateString())
     ->groupBy('user_id')
     ->get();

$values['production_fees'] = \DB::table("transactions")
     ->select(\DB::raw("user_id, SUM(credit_movement) as production_fees"))
     ->whereIn('type', ["Production", "Production Data"])
     ->whereIn('user_id', $userIdsToBeUsed)
     ->whereDate('created_at', '>=', $fromDate->toDateString()) // this is common
     ->whereDate('created_at', '<=', $toDate->toDateString())   // this is common
     ->groupBy('user_id')                                       // this is common
     ->get();

有什么好方法可以将这些查询组合成一个查询,以便我建立 1 个数据库连接来获取所有数据

(我正在寻找 Laravel 查询生成器实现此目的的方法)

您可以使用 UNION 关键字:https://www.w3schools.com/sql/sql_ref_union.asp

所以组合查询将是这样的:

select user_id
     , SUM(credit_movement) as testing_fees
  from transactions
 where `type` in ('Testing', 'Testing Data') 
   and `user_id` in (118,124,352 ...)
group by `user_id`
UNION
select user_id, SUM(credit_movement) as production_fees 
from `transactions` 
where `type` in ('Production', 'Production Data') and `user_id` in (152,521,1341, ...)
group by `user_id`

如果需要允许重复,请使用 UNION ALL 而不是 UNION

如果您想避免混淆哪个是哪个,您可以使用第三个键来告诉您正在处理的数据类型。查看 Laravel docs,您的代码应如下所示:

<?php

$values['testing_fees'] = \DB::table("transactions")
     ->select(\DB::raw("user_id, SUM(credit_movement) as testing_fees,'testing as type'"))
     ->whereIn('type', ["Testing", "Testing Data"])
     ->whereIn('user_id', $userIdsToBeUsed)
     ->whereDate('created_at', '>=', $fromDate->toDateString())
     ->whereDate('created_at', '<=', $toDate->toDateString())
     ->groupBy('user_id');


$values['production_fees'] = \DB::table("transactions")
     ->select(\DB::raw("user_id, SUM(credit_movement) as production_fees,'production' as type"))
     ->whereIn('type', ["Production", "Production Data"])
     ->whereIn('user_id', $userIdsToBeUsed)
     ->whereDate('created_at', '>=', $fromDate->toDateString()) // this is common
     ->whereDate('created_at', '<=', $toDate->toDateString())   // this is common
     ->groupBy('user_id');                                      // this is common


// and so on for $values

$query = array_shift($values);


foreach($values as $key => $sub_query){
    $query->union($sub_query);
}


$data = $query->get();

dd($data);

注意: ->get() 仅在我们 union 编辑了所有子查询后才适用。