Laravel 减少关系查询
Laravel reducing relationship queries
我有两个模型。 Expense
和 Method
。我想为每个 method type
获取所有 expenses
中的 sum
。我有四种类型:
- bank
- credit-card
- wallet
- savings
每个费用都属于一个方法,每个方法都有许多费用。所以这是一个一对多的关系。因此,为每个费用存储一个 method_id
。
以下查询用于获取具有 bank
类型方法的所有费用的总和,例如:
$type = 'bank';
$expenses = auth()->user()->expenses()->with('method')->whereHas('method', function ($query) use ($type) {
$query->where('type', $type);
})->sum('amount');
但问题是,如果我想获得每种方法类型的所有费用总额,我将不得不 运行 查询太多次。我宁愿只获取所有费用,然后过滤它们以获得每种方法类型的所有费用的总和。
以下示例不起作用:
$expenses = auth()->user()->expenses()->with('method')->get();
$bank_balance = $expenses->filter(function ($expense)
{
$expense->whereHas('method', function ($query) {
$query->where('type', 'bank');
})->get(); // with or without ->get()
});
关于如何通过不使用太多查询来获得我想要的内容有什么想法吗?
编辑:
我没有接受所选择的答案,因为它最终没有给我我需要的东西。在我看来,我需要能够做这样的事情:
{{ $bank_balance }}
这意味着,对于 xyz 的回答,我无法做到这一点,因为我无法区分它们。我只得到基于 method_id 的结果,但我需要能够通过方法名称来区分它们。
DigitalDrifter 的回答几乎可以解决问题,但它给了我这个:
Collection {#800 ▼
#items: array:3 [▼
"bank" => Collection {#797 ▼
#items: array:30 [▼
0 => array:2 [▼
"type" => "bank"
"amount" => 1536
]
1 => array:2 [▶]
2 => array:2 [▶]
3 => array:2 [▶]
4 => array:2 [▶]
5 => array:2 [▶]
]
}
"credit-card" => Collection {#798 ▶}
"wallet" => Collection {#799 ▶}
]
}
我基本上需要这样简单的东西:
"bank" => "total sum here for all expenses that have a method of 'bank'"
"credit-card" => "total sum here for all expenses that have a method of 'credit-card'"
等等..
我认为这一点 ->groupBy('type')->each->sum('amount')
可以解决问题,但不完全。它确实按类型分组,但没有给出每种类型的总和,如您在上面的集合示例中所见。
您可以按方法 ID 分组,然后在 select 语句中对结果求和。
以下未测试。
$expenses = auth()->user()
->expenses()
->select(DB::raw('SUM(amount) as total'), 'other_select_fields', ...)
->with('method')
->groupBy('method_id')
->get();
您可以使用可用的收集方法执行此操作:
$expenses = auth()->user()->expenses()->with('method')->get();
$groupedSums = $expenses->map(function ($expense) {
return [
'type' => $expense['method']['type'],
'amount' => $expense['method']['amount']
];
})->groupBy('type')->each->sum('amount');
我有两个模型。 Expense
和 Method
。我想为每个 method type
获取所有 expenses
中的 sum
。我有四种类型:
- bank
- credit-card
- wallet
- savings
每个费用都属于一个方法,每个方法都有许多费用。所以这是一个一对多的关系。因此,为每个费用存储一个 method_id
。
以下查询用于获取具有 bank
类型方法的所有费用的总和,例如:
$type = 'bank';
$expenses = auth()->user()->expenses()->with('method')->whereHas('method', function ($query) use ($type) {
$query->where('type', $type);
})->sum('amount');
但问题是,如果我想获得每种方法类型的所有费用总额,我将不得不 运行 查询太多次。我宁愿只获取所有费用,然后过滤它们以获得每种方法类型的所有费用的总和。
以下示例不起作用:
$expenses = auth()->user()->expenses()->with('method')->get();
$bank_balance = $expenses->filter(function ($expense)
{
$expense->whereHas('method', function ($query) {
$query->where('type', 'bank');
})->get(); // with or without ->get()
});
关于如何通过不使用太多查询来获得我想要的内容有什么想法吗?
编辑:
我没有接受所选择的答案,因为它最终没有给我我需要的东西。在我看来,我需要能够做这样的事情:
{{ $bank_balance }}
这意味着,对于 xyz 的回答,我无法做到这一点,因为我无法区分它们。我只得到基于 method_id 的结果,但我需要能够通过方法名称来区分它们。
DigitalDrifter 的回答几乎可以解决问题,但它给了我这个:
Collection {#800 ▼
#items: array:3 [▼
"bank" => Collection {#797 ▼
#items: array:30 [▼
0 => array:2 [▼
"type" => "bank"
"amount" => 1536
]
1 => array:2 [▶]
2 => array:2 [▶]
3 => array:2 [▶]
4 => array:2 [▶]
5 => array:2 [▶]
]
}
"credit-card" => Collection {#798 ▶}
"wallet" => Collection {#799 ▶}
]
}
我基本上需要这样简单的东西:
"bank" => "total sum here for all expenses that have a method of 'bank'" "credit-card" => "total sum here for all expenses that have a method of 'credit-card'"
等等..
我认为这一点 ->groupBy('type')->each->sum('amount')
可以解决问题,但不完全。它确实按类型分组,但没有给出每种类型的总和,如您在上面的集合示例中所见。
您可以按方法 ID 分组,然后在 select 语句中对结果求和。
以下未测试。
$expenses = auth()->user()
->expenses()
->select(DB::raw('SUM(amount) as total'), 'other_select_fields', ...)
->with('method')
->groupBy('method_id')
->get();
您可以使用可用的收集方法执行此操作:
$expenses = auth()->user()->expenses()->with('method')->get();
$groupedSums = $expenses->map(function ($expense) {
return [
'type' => $expense['method']['type'],
'amount' => $expense['method']['amount']
];
})->groupBy('type')->each->sum('amount');