SQL查询:如何获取收发方唯一值并剔除反向重复记录?
解决无序对去重的SQL方案
要搞定这个反向重复记录的问题,核心思路是把每一组sender和receiver转化为固定顺序的无序对,让(1,5)和(5,1)变成同一个组合,再用DISTINCT去重即可。结合你需要保留5-1、2-6这类示例的要求,我分几种常见场景给你提供可行方案:
方案1:强制按“大数在前、小数在后”输出(匹配你示例里的5-1组合)
如果你的需求是统一保留数值大的在前、小的在后的组合,可以用条件函数重组字段:
MySQL/MariaDB 写法
SELECT DISTINCT CASE WHEN sender > receiver THEN sender ELSE receiver END AS first_id, CASE WHEN sender > receiver THEN receiver ELSE sender END AS second_id FROM `table`;
PostgreSQL 写法
PostgreSQL自带GREATEST(取最大值)和LEAST(取最小值)函数,代码更简洁:
SELECT DISTINCT GREATEST(sender, receiver) AS first_id, LEAST(sender, receiver) AS second_id FROM "table";
方案2:严格保留反向组合中后出现的那条记录
如果你的需求不是按数值排序,而是要保留每对反向组合里最后插入数据库的那条记录,那需要依赖一个能判断顺序的字段(比如自增主键id、创建时间create_time)。假设表中有自增主键id,可以这样写:
SELECT t.sender, t.receiver FROM `table` t WHERE t.id = ( SELECT MAX(id) FROM `table` WHERE (sender = t.sender AND receiver = t.receiver) OR (sender = t.receiver AND receiver = t.sender) ) GROUP BY t.sender, t.receiver;
这个查询会找出每一对无序组合中ID最大的那条记录,也就是最后插入的那条,完美匹配你“保留后者”的要求。
方案3:仅去重无序对,不关心保留哪一个
如果只是需要消除反向重复,不纠结保留哪一个组合,方案1的写法完全够用——它会统一输出固定顺序的组合,从根源上避免反向重复。
示例验证
假设你的表中有以下数据:
| msg | sender | receiver |
|---|---|---|
| ... | 1 | 5 |
| ... | 5 | 1 |
| ... | 6 | 2 |
| ... | 2 | 6 |
用方案1的PostgreSQL语句会返回:
| first_id | second_id |
|---|---|
| 5 | 1 |
| 6 | 2 |
如果用方案2(假设(5,1)的ID比(1,5)大,(2,6)的ID比(6,2)大),会返回:
| sender | receiver |
|---|---|
| 5 | 1 |
| 2 | 6 |
完全符合你的示例预期~
内容的提问来源于stack exchange,提问作者Robiul Islam
相关产品推荐
相关产品推荐

