You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何从关联表获取仅参加单个活动的用户

Laravel多对多关联:查询仅参加单个活动的用户

需求说明

在Laravel应用中,users表与activities表为多对多关系,中间关联表为activity_users(包含user_id和activity_id字段)。需要从指定活动的报名用户中,筛选出仅参加了这一个活动的用户,要求直接在数据库层面完成过滤,避免查询后再筛选的低效方案。

示例表结构

表users

idname
1User A
2User B

表activities

idname
1Activity 1
2Activity 2

表activity_users

activity_iduser_id
11
12
21

根据示例数据:

  • 查询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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:33:21