Laravel中如何从关联表获取仅参加单个活动的用户
Laravel多对多关联:查询仅参加单个活动的用户
需求说明
在Laravel应用中,users表与activities表为多对多关系,中间关联表为activity_users(包含user_id和activity_id字段)。需要从指定活动的报名用户中,筛选出仅参加了这一个活动的用户,要求直接在数据库层面完成过滤,避免查询后再筛选的低效方案。
示例表结构
表users
| id | name |
|---|---|
| 1 | User A |
| 2 | User B |
表activities
| id | name |
|---|---|
| 1 | Activity 1 |
| 2 | Activity 2 |
表activity_users
| activity_id | user_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
根据示例数据:
- 查询
Activity 1应返回User B(仅参加此活动) - 查询
Activity 2应返回空结果(唯一报名用户同时参加了其他活动)
数据库层面解决方案
方法1:Eloquent关联+统计筛选
通过whereHas先锁定指定活动的用户,再筛选出总活动数为1的用户:
$targetActivityId = 1; $users = User::whereHas('activities', function ($query) use ($targetActivityId) { // 筛选出参加了目标活动的用户 $query->where('activities.id', $targetActivityId); }) ->whereHas('activities', function ($query) { // 筛选出仅参加1个活动的用户 $query->groupBy('activity_users.user_id') ->havingRaw('COUNT(DISTINCT activities.id) = 1'); }) ->get();
方法2:子查询过滤(高效简洁)
通过两次子查询取交集,先获取目标活动的用户ID,再筛选出仅参加1个活动的用户ID:
$targetActivityId = 1; $users = User::whereIn('id', function ($query) use ($targetActivityId) { // 子查询1:获取目标活动的报名用户ID $query->select('user_id') ->from('activity_users') ->where('activity_id', $targetActivityId); }) ->whereIn('id', function ($query) { // 子查询2:获取仅参加1个活动的用户ID $query->select('user_id') ->from('activity_users') ->groupBy('user_id') ->havingRaw('COUNT(activity_id) = 1'); }) ->get();
方法3:JOIN关联过滤(性能最优)
通过左关联中间表,直接排除有其他活动记录的用户,数据库层面一步完成过滤:
use Illuminate\Support\Facades\DB; $targetActivityId = 1; $users = User::join('activity_users as au_target', 'users.id', '=', 'au_target.user_id') ->leftJoin('activity_users as au_other', function ($join) use ($targetActivityId) { // 左关联用户的其他活动记录 $join->on('users.id', '=', 'au_other.user_id') ->where('au_other.activity_id', '!=', $targetActivityId); }) ->where('au_target.activity_id', $targetActivityId) ->whereNull('au_other.activity_id') // 无其他活动记录 ->select('users.*') ->distinct() // 中间表已做唯一约束,可省略 ->get();
说明
以上方案均在数据库层面完成筛选,避免了内存中过滤全量数据的低效操作;其中方法3的JOIN方式性能最优,通过关联直接排除不符合条件的用户,无需额外分组统计。
内容的提问来源于stack exchange,提问作者iamsubingyawali
相关产品推荐
相关产品推荐

