很长时间以来,我一直在寻找这个问题的解决方案:
假设我们有2个表,其中一个表是Clients表,第二个表是ClientAssignment表:
ClientAssignment表与Clients表相关:
public function assignment()
{
return $this->hasOne(ClientAssignment::class, 'client_id');
}
现在,当我想计算有多少ClientAssignment的客户时,我这样做:
$users =[1,2,3,4 .....]
$userAssignments = array();
foreach ($users as $user) {
$user_assignments = Client::whereHas('assignment', function ($query) use ($user) {
$query->where('assigned_id', $user);
});
$ua['user_id'] = $user;
$ua['count'] = $user_assignments->count();
array_push($userAssignments, $ua);
}
该代码运行良好,但在具有80k个客户端的相对较小的表上,其性能和查询执行时间达到〜20 +秒,
我的问题是否可以是做同一件事的另一种方法,但是性能最低且查询执行时间短?
最佳答案
根据您的帖子,我认为
Client --- hasOne ----> ClientAssignment <----- hasMany ---- User
[client_id, assigned_id]
因此
User
可以通过Client
拥有很多ClientAssignment
,但是,您的
client_id
和assigned_id
都在client_assignment
表中。因此,您不能像透视表那样使用hasManyThrough
。幸运的是,您可以直接计算
client_id
并获得assigned_id
作为user_id
,只需使用此数据透视表即可。查询是这样的(使用
distinct(client_id)
防止脏记录):ClientAssignment::whereIn('assigned_id', $users)
->groupBy('assigned_id')
->select('assigned_id AS user_id',
DB::raw('COUNT(DISTINCT(client_id)) AS count'))
->get()->toArray();
并添加
assigned_id
索引以提高性能。$table->index('assigned_id');