Laravel中按用户统计路线计划数及总门店数的实现求助
解决方案
可以通过子查询或集合遍历两种方式实现按用户汇总门店总数,以下是具体方案:
方案1:子查询统计(高性能推荐)
直接在用户查询中嵌入子查询,跨关联层级计算符合条件的门店总数,避免重复计数:
$users = User::select('id', 'name', 'code') ->withCount(['todaysAssignedRoutePlans as total_route']) ->selectSub(function ($query) use ($outletIds) { $query->selectRaw('COUNT(DISTINCT o.id)') ->from('todays_assigned_route_plans as tarp') ->join('territories as t', 'tarp.territory_id', '=', 't.id') ->join('outlets as o', 't.id', '=', 'o.territory_id') ->whereIn('o.id', $outletIds) ->whereColumn('tarp.assigned_to', 'users.id'); }, 'total_outlet') ->get();
说明:
- 子查询通过
users→todays_assigned_route_plans→territories→outlets的关联关系,用COUNT(DISTINCT o.id)确保同一门店不会因多个路线计划重复统计。 whereColumn将子查询与外层用户表绑定,保证每个用户只统计自身关联的数据。- 保留原有
total_route的统计逻辑,无需修改。
方案2:集合遍历统计(小数据量适用)
如果数据规模不大,可在查询完成后手动遍历集合汇总:
$users = User::select('id', 'name','code') ->with(['todaysAssignedRoutePlans.territory' => function ($q) use ($outletIds) { $q->withCount(['outlets as distinct_outlets' => function ($q) use ($outletIds) { $q->whereIn('id', $outletIds)->distinct(); }]); }]) ->withCount(['todaysAssignedRoutePlans as total_route']) ->get() ->map(function ($user) { // 先去重关联的区域,再求和门店数 $uniqueTerritories = $user->todaysAssignedRoutePlans->pluck('territory')->unique('id'); $user->total_outlet = $uniqueTerritories->sum('distinct_outlets'); return $user; });
说明:
- 预加载关联的
territory及其门店计数,通过unique('id')排除重复区域,避免同一区域被多个路线计划重复统计。 - 该方案无需调整查询结构,但数据量大时性能低于方案1。
注意事项
- 请根据实际数据库表名调整示例中的表名(如
todays_assigned_route_plans、territories)。 - 若
Outlet与Territory的关联字段不是territory_id,需修改对应的JOIN条件。
内容的提问来源于stack exchange,提问作者Rakibul Islam
相关产品推荐
相关产品推荐

