Oracle SQL:移除仅单字段不同的重复记录(保留非空值)
解决方案:移除分组中含NULL的重复记录
我来帮你搞定这个问题!从你的描述来看,核心问题是同一field2分组下存在field1为NULL和非空的两条记录,而你想只保留非空的那条。之前尝试的方法没生效,大概率是因为原查询的GROUP BY包含了field1,导致NULL和非空值被分成了两个独立分组,所以才会出现两条记录。
下面给你两个实用的解决方案:
方法一:利用MAX()聚合+分组过滤
既然非空字符串的排序优先级高于NULL,我们可以通过MAX(t1.field1)直接提取每个field2分组下的非空值,同时用HAVING过滤掉那些只有NULL的分组(如果不需要保留这类分组的话)。修改后的查询如下:
SELECT t2.field2, MAX(t1.field1) AS field1 FROM table1 t1 JOIN table2 t2 ON t1.primary_key = t2.primary_key GROUP BY t2.field2 -- 可选:如果需要保留field2对应field1全为NULL的记录,去掉下面这行 HAVING MAX(t1.field1) IS NOT NULL;
为什么这个方法有效?
MAX()函数会自动忽略NULL值,返回分组内最大的非空值(字符串类型下非空值一定比NULL大)- 只按
field2分组,确保每个field2只返回一条记录 - 可选的
HAVING子句可以过滤掉那些分组内全是NULL的情况
方法二:用窗口函数标记优先级
如果需要更灵活的控制(比如保留所有field2分组,哪怕只有NULL),可以用ROW_NUMBER()窗口函数给记录标记优先级,优先保留非空的field1记录:
WITH ranked_records AS ( SELECT t1.field1, t2.field2, -- 给非空field1标记行号1,NULL标记行号2 ROW_NUMBER() OVER ( PARTITION BY t2.field2 ORDER BY CASE WHEN t1.field1 IS NOT NULL THEN 1 ELSE 2 END ) AS rn FROM table1 t1 JOIN table2 t2 ON t1.primary_key = t2.primary_key ) SELECT field1, field2 FROM ranked_records WHERE rn = 1 -- 可选:如果要完全移除field1为NULL的记录,再加下面这行 -- AND field1 IS NOT NULL;
这个方法的优势:
- 可以清晰控制记录的优先级排序逻辑
- 即使某个
field2只有NULL记录,也可以选择保留或移除 - 不会改变原表的字段结构,适合需要保留多个字段的场景
为什么你之前的尝试没生效?
你提到用了MAX(t1.field1)但结果没变化,应该是原查询的GROUP BY同时包含了t1.field1和t2.field2——这会把field1的NULL和非空值当成两个不同的分组,自然会返回两条记录。只要把GROUP BY改成只按t2.field2分组,MAX()就能正常提取非空值了。
内容的提问来源于stack exchange,提问作者1131
相关产品推荐
相关产品推荐

