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

如何在Laravel中编写去除双向重复匹配记录的查询语句

解决双向重复记录的查询优化问题

你的表中存在双向重复的记录(如(101,102)和(102,101)),当前的distinct()无法生效,因为这两条记录的字段值顺序不同,属于不同的行。以下是几种可行的修改方案:

方案一:筛选单向记录(简单直接)

直接保留user_id小于to_user_id的记录,自动排除反向的重复项:

$query = \App\Models\MyMatch::query();
$query->whereHas('users')
    ->whereHas('tousers')
    ->where('user_id', '!=', 'to_user_id')
    ->whereRaw('user_id < to_user_id');
$records = $query->get();

这种方法会保留(101,102)和(101,105),正好符合你的预期。如果存在单向的记录(比如只有(103,104)没有反向),也会正常保留。

方案二:分组去重(更灵活)

通过将每对用户的最小ID和最大ID作为分组依据,确保每对只保留一条记录:

$query = \App\Models\MyMatch::query();
$query->whereHas('users')
    ->whereHas('tousers')
    ->where('user_id', '!=', 'to_user_id')
    ->selectRaw('my_matches.*, LEAST(user_id, to_user_id) as min_user, GREATEST(user_id, to_user_id) as max_user')
    ->groupBy('min_user', 'max_user');
$records = $query->get();

注意:如果你的MySQL开启了严格模式,需要确保group by包含所有非聚合字段,或者调整配置允许非严格分组,也可以改用子查询先获取唯一的用户对,再关联原表取记录。

方案三:子查询排除反向记录(最严谨)

通过子查询检查是否存在反向记录,仅保留每对中user_id更小的那条:

$query = \App\Models\MyMatch::query();
$query->whereHas('users')
    ->whereHas('tousers')
    ->where('user_id', '!=', 'to_user_id')
    ->whereNotExists(function ($subQuery) {
        $subQuery->select(\DB::raw(1))
            ->from('my_matches as mm')
            ->whereColumn('mm.user_id', '=', 'my_matches.to_user_id')
            ->whereColumn('mm.to_user_id', '=', 'my_matches.user_id')
            ->whereColumn('mm.user_id', '>', 'my_matches.user_id');
    });
$records = $query->get();

这个方法会确保每一对双向记录只保留一条,同时不会影响单向存在的记录。

内容的提问来源于stack exchange,提问作者bidiyal536

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:10:16