SQL Server 2016删除双列重复行及现有查询异常咨询
你的查询问题分析&删除重复行的正确方法
咱们先拆解下你原查询的问题,再一步步解决删除重复行的需求:
原查询为啥返回全表?
你的查询逻辑完全偏离了“找CertID+ResponseDueDate组合重复”的需求,问题出在这几点:
- CTE A的DISTINCT无效:你用了
DISTINCT ID, ResponseDueDate, CertID,但ID是表的唯一标识(看你的示例数据,每行ID都不一样),所以每一行的这三个字段组合都是唯一的,DISTINCT等于没加,A其实就是原表的全部数据。 - CTE B的分组逻辑错误:你按CertID分组并筛选
COUNT(*) >1,这是在找“对应多个行的CertID”,但你的需求是找“CertID+ResponseDueDate组合重复”的行。示例数据里所有行的CertID都是48983,所以B会包含这个CertID,最后关联后自然返回全表。
如何删除多余的重复行(保留每组组合的一行)?
针对SQL Server 2016,推荐两种可靠的方法,操作前一定要先备份数据,或者先执行SELECT确认要删除的行,避免误删:
方法1:用ROW_NUMBER()窗口函数(逻辑最清晰)
给每个CertID+ResponseDueDate组合的行分配编号,保留编号为1的行,删除编号大于1的。你可以通过ORDER BY指定保留哪一行(比如保留ID最小的,或者最新的记录):
先确认要删除的行:
SELECT ID, CertID, ResponseDueDate, -- 按组合分组,给行编号,ID小的排前面 ROW_NUMBER() OVER(PARTITION BY CertID, ResponseDueDate ORDER BY ID) AS RowNum FROM FacCompliance ORDER BY CertID, ResponseDueDate, RowNum;
执行删除:
WITH DuplicateRows AS ( SELECT ID, ROW_NUMBER() OVER(PARTITION BY CertID, ResponseDueDate ORDER BY ID) AS RowNum FROM FacCompliance ) DELETE FROM DuplicateRows WHERE RowNum > 1;
如果想保留ID最大的行,把ORDER BY ID改成ORDER BY ID DESC即可。
方法2:用自连接删除
通过自连接找到重复组合中需要删除的行(比如ID更大的行),直接删除:
DELETE f1 FROM FacCompliance f1 JOIN FacCompliance f2 ON f1.CertID = f2.CertID AND f1.ResponseDueDate = f2.ResponseDueDate AND f1.ID > f2.ID; -- 保留ID较小的行,删除ID更大的重复行
内容的提问来源于stack exchange,提问作者NoBullMan
相关产品推荐
相关产品推荐

