如何在Laravel Eloquent中用withCount合并两个关联表的统计数?
用Eloquent withCount直接合并统计friends_reactions与friends_activities的总数
你可以通过以下几种方式实现预加载时直接获取合并后的engagements_count:
方法一:在withCount中使用子查询合并统计
直接在withCount的闭包里通过unionAll合并两个表的关联数据,再统计总数:
use Illuminate\Support\Facades\DB; $friends = Friend::withCount([ // 保留原有单独统计(可选) 'reactions', 'activities', // 合并统计engagements 'engagements' => function ($query) { $query->select(DB::raw('COUNT(*)')) ->fromSub(function ($sub) { // 合并两个表的friend_id $sub->select('friend_id') ->from('friends_reactions') ->unionAll( DB::table('friends_activities')->select('friend_id') ); }, 'combined_engagements') ->whereColumn('combined_engagements.friend_id', 'friends.id'); } ])->get();
查询完成后,每个Friend实例会自动带上engagements_count字段,即两个表的记录总数之和。
方法二:自定义关联后用withCount统计
先在Friend.php模型中定义一个合并了reactions和activities的关联:
use Illuminate\Support\Facades\DB; public function engagements() { return $this->fromQuery( DB::table('friends_reactions') ->select('friend_id') ->unionAll(DB::table('friends_activities')->select('friend_id')) ->whereColumn('friend_id', 'friends.id') ); }
之后直接通过withCount统计这个关联即可:
$friends = Friend::withCount('engagements')->get();
拓展:添加过滤条件
如果需要针对特定type的记录统计,可以在子查询中添加where条件:
public function engagements() { return $this->fromQuery( DB::table('friends_reactions') ->select('friend_id') ->where('type', 'like') // 只统计点赞类的reactions ->unionAll( DB::table('friends_activities') ->select('friend_id') ->where('type', 'comment') // 只统计评论类的activities ) ->whereColumn('friend_id', 'friends.id') ); }
方法三:基于已有count字段相加(简洁版)
如果不需要从数据库层面合并统计,也可以直接利用已有的reactions_count和activities_count,通过selectRaw计算总和:
$friends = Friend::withCount(['reactions', 'activities']) ->selectRaw('friends.*, (reactions_count + activities_count) as engagements_count') ->get();
这个方式代码更简洁,适合不需要复杂过滤的场景。
内容的提问来源于stack exchange,提问作者Duka
相关产品推荐
相关产品推荐

