SQL技术问询:特定条件下重复行的处理方案
处理重复行的SQL解决方案
看起来你是要处理表中同一用户的重复行问题——比如示例里的John,一行有牙齿区域的数据,另一行只有服务记录但牙齿字段全为空。下面给你两种常见场景的SQL解决方案,你可以根据实际需求选择:
原始数据表
| ID | Name | RecievedService | FirstZoneTeeth | SecondZoneTeeth | ThirdZoneTeeth | FourthZoneTeeth |
|---|---|---|---|---|---|---|
| 1 | John | SomeService1 | 13 | 4 | ||
| 2 | John | SomeService... |
场景1:合并重复行的非空数据
如果需要保留所有服务记录,同时把同一用户的牙齿数据填充到每一行中(避免空值),可以用CTE结合聚合函数来实现:
WITH user_teeth_summary AS ( SELECT Name, -- MAX会自动忽略空值,取每个用户对应的非空牙齿数据 MAX(FirstZoneTeeth) AS FirstZoneTeeth, MAX(SecondZoneTeeth) AS SecondZoneTeeth, MAX(ThirdZoneTeeth) AS ThirdZoneTeeth, MAX(FourthZoneTeeth) AS FourthZoneTeeth FROM your_table_name GROUP BY Name ) SELECT t.ID, t.Name, t.RecievedService, uts.FirstZoneTeeth, uts.SecondZoneTeeth, uts.ThirdZoneTeeth, uts.FourthZoneTeeth FROM your_table_name t JOIN user_teeth_summary uts ON t.Name = uts.Name;
执行后,John的两行记录都会带上FirstZoneTeeth=13和ThirdZoneTeeth=4的非空数据。
场景2:删除无有效数据的重复行
如果只需要保留每个用户包含牙齿数据的那一行,删掉没有任何牙齿信息的重复行,可以用两种方式实现:
方式1:用子查询筛选保留行
-- 先确认要保留的行(建议先执行SELECT验证) SELECT MAX(ID) AS keep_id FROM your_table_name WHERE FirstZoneTeeth IS NOT NULL OR SecondZoneTeeth IS NOT NULL OR ThirdZoneTeeth IS NOT NULL OR FourthZoneTeeth IS NOT NULL GROUP BY Name; -- 确认无误后执行删除 DELETE FROM your_table_name WHERE ID NOT IN ( SELECT MAX(ID) FROM your_table_name WHERE FirstZoneTeeth IS NOT NULL OR SecondZoneTeeth IS NOT NULL OR ThirdZoneTeeth IS NOT NULL OR FourthZoneTeeth IS NOT NULL GROUP BY Name );
这里用MAX(ID)是保留每个用户最新的有效行,如果你想保留最早的,换成MIN(ID)即可。
方式2:用窗口函数更灵活排序
如果需要更复杂的优先级(比如同时考虑服务时间、数据完整性),窗口函数是更好的选择:
WITH ranked_records AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY -- 优先保留有牙齿数据的行 CASE WHEN FirstZoneTeeth IS NOT NULL OR SecondZoneTeeth IS NOT NULL OR ThirdZoneTeeth IS NOT NULL OR FourthZoneTeeth IS NOT NULL THEN 0 ELSE 1 END, ID DESC -- 同优先级下保留最新的行 ) AS row_rank FROM your_table_name ) -- 先执行SELECT看要删除的行 SELECT * FROM ranked_records WHERE row_rank > 1; -- 确认后删除 DELETE FROM your_table_name WHERE ID IN (SELECT ID FROM ranked_records WHERE row_rank > 1);
重要提示
- 记得把
your_table_name替换成你实际使用的表名 - 如果
Name不是用户的唯一标识(比如有重名),要把分组依据换成用户的唯一ID字段 - 执行删除操作前一定要先运行对应的SELECT语句验证,避免误删数据
内容的提问来源于stack exchange,提问作者Shaho
相关产品推荐
相关产品推荐

