如何在SQL Server中移除仅单列不同的指定重复行?
如何过滤重复行并保留指定记录?
原始数据
| ID | Val1 | Val2 | Val3 | Val4 | Val5 | SomeVal |
|---|---|---|---|---|---|---|
| 1111 | 'Value0 1' | 'Value0 2' | 'Value0 3' | 'Value0 4' | 'Value0 5' | NULL |
| 1111 | 'Value0 1' | 'Value0 2' | 'Value0 3' | 'Value0 4' | 'Value0 5' | 'Some Value0' |
| 2222 | 'Value1 1' | 'Value1 2' | 'Value1 3' | 'Value1 4' | 'Value1 5' | NULL |
| 2222 | 'Value1 1' | 'Value1 2' | 'Value1 3' | 'Value1 4' | 'Value1 5' | 'Some Value1' |
| 3333 | 'Value3 1' | 'Value3 2' | 'Value3 3' | 'Value3 4' | 'Value3 5' | NULL |
| 4444 | 'Value4 1' | 'Value4 2' | 'Value4 3' | 'Value4 4' | 'Value4 5' | NULL |
需求说明
过滤掉ID、Val1-Val5完全重复且SomeVal为NULL的行,保留两类记录:
- SomeVal非空的行
- 同组内没有对应非空行的SomeVal为NULL的行
最终需要移除的是以下两行:
| ID | Val1 | Val2 | Val3 | Val4 | Val5 | SomeVal |
|---|---|---|---|---|---|---|
| 1111 | 'Value0 1' | 'Value0 2' | 'Value0 3' | 'Value0 4' | 'Value0 5' | NULL |
| 2222 | 'Value1 1' | 'Value1 2' | 'Value1 3' | 'Value1 4' | 'Value1 5' | NULL |
解决方案
方法1:窗口函数分组统计
按ID和Val1-Val5分组,统计每组中SomeVal非空的记录数。如果组内存在非空记录,就只保留非空行;如果没有,就保留原有的NULL行。
WITH grouped_data AS ( SELECT *, COUNT(SomeVal) OVER (PARTITION BY ID, Val1, Val2, Val3, Val4, Val5) AS non_null_count FROM your_table ) SELECT ID, Val1, Val2, Val3, Val4, Val5, SomeVal FROM grouped_data WHERE SomeVal IS NOT NULL OR non_null_count = 0;
方法2:EXISTS子查询判断
对于每一行:
- 如果SomeVal非空,直接保留
- 如果SomeVal是NULL,检查同组内是否存在非空记录,不存在则保留,存在则过滤
SELECT t1.* FROM your_table t1 WHERE t1.SomeVal IS NOT NULL OR NOT EXISTS ( SELECT 1 FROM your_table t2 WHERE t2.ID = t1.ID AND t2.Val1 = t1.Val1 AND t2.Val2 = t1.Val2 AND t2.Val3 = t1.Val3 AND t2.Val4 = t1.Val4 AND t2.Val5 = t1.Val5 AND t2.SomeVal IS NOT NULL );
关于LEAD函数的适用性
LEAD函数可以查看下一行的SomeVal值,但它依赖于行的排序顺序,如果同组内的NULL行和非空行不相邻,就会判断错误。而且它只能处理相邻行的情况,无法覆盖整个分组的所有记录,稳定性不如上面两种方法,因此不推荐使用。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

