如何在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
相关产品推荐
相关产品推荐

