Oracle SQL:如何排除列值顺序不同的重复组合行?
Oracle SQL 排除列值组合重复行的解决方案
你之前用的WHERE column1+column2+column3+column4 != column3+column4+column1+column2完全无效——因为同一行里这两个拼接字符串必然相等,这个条件会把所有行都过滤掉,根本达不到去重目的。
要解决这种“四个列值顺序调换但组合重复”的去重需求,核心思路是:给每组值相同(不管顺序)的行生成一个固定顺序的唯一标识,然后基于这个标识分组,每组只保留一行。
下面提供两种可行的实现方案:
方案一:用LEAST/GREATEST嵌套生成排序标识
通过嵌套使用LEAST和GREATEST函数,把四个列的值按从小到大的顺序拼接成唯一字符串,作为分组依据。适用于列值类型统一(字符串或数值)的场景:
SELECT column1, column2, column3, column4 FROM ( SELECT t.*, ROW_NUMBER() OVER ( PARTITION BY -- 生成按升序排列的四列组合字符串(处理NULL值) LEAST(NVL(column1, 'NULL'), NVL(column2, 'NULL'), NVL(column3, 'NULL'), NVL(column4, 'NULL')) || GREATEST(LEAST(NVL(column1, 'NULL'), NVL(column2, 'NULL'), NVL(column3, 'NULL')), LEAST(GREATEST(NVL(column1, 'NULL'), NVL(column2, 'NULL')), NVL(column3, 'NULL'), NVL(column4, 'NULL'))) || LEAST(GREATEST(NVL(column1, 'NULL'), NVL(column2, 'NULL'), NVL(column3, 'NULL')), GREATEST(NVL(column1, 'NULL'), NVL(column3, 'NULL'), NVL(column4, 'NULL')), GREATEST(NVL(column2, 'NULL'), NVL(column3, 'NULL'), NVL(column4, 'NULL'))) || GREATEST(NVL(column1, 'NULL'), NVL(column2, 'NULL'), NVL(column3, 'NULL'), NVL(column4, 'NULL')) ORDER BY column1, column2 -- 可根据需求指定保留哪一行的排序规则 ) AS rn FROM your_table t ) WHERE rn = 1;
- 注:如果列是数值类型,把
NVL里的'NULL'换成0或其他合适的默认值即可,避免NULL干扰分组逻辑。
方案二:用UNPIVOT+LISTAGG生成排序标识
通过UNPIVOT把四个列转成行数据,再用LISTAGG按值排序后拼接成字符串,逻辑更直观,适合列类型多样的场景:
SELECT column1, column2, column3, column4 FROM ( SELECT original.*, ROW_NUMBER() OVER ( PARTITION BY sorted_cols ORDER BY column1, column2 -- 可自定义保留行的排序规则 ) AS rn FROM ( SELECT original.column1, original.column2, original.column3, original.column4, LISTAGG(NVL(col_val, 'NULL'), ',') WITHIN GROUP (ORDER BY col_val) AS sorted_cols FROM your_table original UNPIVOT ( col_val FOR col_name IN (column1, column2, column3, column4) ) GROUP BY original.column1, original.column2, original.column3, original.column4 ) t ) WHERE rn = 1;
- 注:如果原表有其他需要保留的列,要在
GROUP BY和外层SELECT中一并添加。
内容的提问来源于stack exchange,提问作者user2799022
相关产品推荐
相关产品推荐

