如何在SQL中去除两列值顺序不同的重复数据
解决列值顺序不同的重复行去重问题
你的场景里,DISTINCT之所以失效,是因为它只会识别完全相同的整行,而(13,24)和(24,13)属于列值顺序颠倒的不同行,所以无法被去重。下面提供几种通用的解决方法:
方法1:用LEAST/GREATEST函数快速生成有序组合
大部分主流数据库(MySQL、PostgreSQL、SQL Server等)都支持LEAST()(取最小值)和GREATEST()(取最大值)函数,通过把两列转换成固定顺序的组合,再用DISTINCT去重:
得到结果一(小值在前,大值在后)
SELECT DISTINCT LEAST(ColumnA, ColumnB) AS ColumnA, GREATEST(ColumnA, ColumnB) AS ColumnB FROM your_table;
得到结果二(大值在前,小值在后)
只需调换两个函数的位置:
SELECT DISTINCT GREATEST(ColumnA, ColumnB) AS ColumnA, LEAST(ColumnA, ColumnB) AS ColumnB FROM your_table;
方法2:用CASE语句兼容不支持LEAST/GREATEST的数据库
如果你的数据库不提供上述函数,可以用CASE手动判断列值大小,生成有序组合:
SELECT DISTINCT CASE WHEN ColumnA <= ColumnB THEN ColumnA ELSE ColumnB END AS ColumnA, CASE WHEN ColumnA <= ColumnB THEN ColumnB ELSE ColumnA END AS ColumnB FROM your_table;
方法3:保留原表中的特定行(如最早插入的记录)
如果需要保留原表中某一行的原始顺序(而不是强制排序),比如保留主键最小的那一行,可以用分组或窗口函数实现:
子查询分组方式
假设表有主键id:
SELECT ColumnA, ColumnB FROM your_table t WHERE id = ( SELECT MIN(id) FROM your_table WHERE (ColumnA = t.ColumnA AND ColumnB = t.ColumnB) OR (ColumnA = t.ColumnB AND ColumnB = t.ColumnA) );
窗口函数方式(更灵活)
WITH ranked_rows AS ( SELECT ColumnA, ColumnB, ROW_NUMBER() OVER ( PARTITION BY LEAST(ColumnA, ColumnB), GREATEST(ColumnA, ColumnB) ORDER BY id -- 可替换为时间戳等排序字段,控制保留哪一行 ) AS rn FROM your_table ) SELECT ColumnA, ColumnB FROM ranked_rows WHERE rn = 1;
内容的提问来源于stack exchange,提问作者C.Dinç
相关产品推荐
相关产品推荐

