如何编写SQL消除相同产品对的重复行,保留唯一组合
解决无序产品对的重复行删除问题
首先咱们明确核心需求:当ProductA和ProductB是互为交换的组合(比如XX&CC与CC&XX),且Count值一致时,这些行属于重复项,需要仅保留其中一行。
先验证:查询出无重复的结果集
可以利用LEAST()和GREATEST()函数把无序的产品对统一成固定顺序——把两个产品字段里字典序更小的放在前面、更大的放在后面,这样同一组交换的产品对会被归为同一组。再结合窗口函数给每组重复行编号,只保留编号为1的行:
WITH ranked_rows AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY LEAST(ProductA, ProductB), GREATEST(ProductA, ProductB), Count ORDER BY ProductA -- 这里可以自定义保留规则,比如优先保留ProductA更小的行 ) AS rn FROM your_table_name ) SELECT ProductA, ProductB, Count FROM ranked_rows WHERE rn = 1;
执行后会得到你预期的结果:
ProductA ProductB Count XX CC 2 ZZ XX 3
直接删除表中的重复行(适用于支持CTE的数据库)
如果你的数据库是MySQL 8.0+、PostgreSQL、SQL Server这类支持CTE和DELETE操作的,可以用下面的语句直接清理重复行:
WITH ranked_rows AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY LEAST(ProductA, ProductB), GREATEST(ProductA, ProductB), Count ORDER BY ProductA ) AS rn FROM your_table_name ) DELETE FROM ranked_rows WHERE rn > 1;
兼容旧版本数据库的方案(无需窗口函数)
如果你的数据库不支持窗口函数,也可以通过自连接的方式删除重复行,只保留ProductA字典序小于ProductB的那一行:
DELETE t1 FROM your_table_name t1 JOIN your_table_name t2 ON t1.Count = t2.Count AND t1.ProductA = t2.ProductB AND t1.ProductB = t2.ProductA AND t1.ProductA > t2.ProductA; -- 删除ProductA更大的重复行,保留更小的那行
⚠️ 注意事项:
- 替换语句中的
your_table_name为你实际的表名 - 执行删除操作前,建议先运行查询语句验证结果,确保符合预期再执行删除
- 如果表有主键,用主键关联会更高效,也能避免因
Count值巧合相同导致的误删
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

