SQL Server 删除表中重复数据的两种高效方法
在处理关系型数据库时,数据清洗往往面临去重难题。针对 SQL Server 环境,若表结构包含唯一主键或索引列,直接通过逻辑判断剔除多余记录最为稳妥;反之,对于缺乏独立标识的宽表,利用 ROW_NUMBER() 窗口函数进行分组排序是通用且高效的解决方案。
准备示例数据
为了演示去重过程,首先创建一个包含 ID 和 Name 字段的临时表,并插入若干模拟数据,其中 Name 字段存在重复项:
CREATE TABLE Student(
ID varchar(10) NOT NULL,
Name varchar(10) NOT NULL
);
INSERT INTO Student VALUES('1', 'zhangs');
INSERT INTO Student VALUES('2', 'zhangs');
INSERT INTO Student VALUES('3', 'lisi');
INSERT INTO Student VALUES('4', 'lisi');
INSERT INTO Student VALUES('5', 'wangwu');
目标是将所有重复的姓名合并,使得每个姓名仅对应一条记录。
方法一:利用唯一标识列删除重复记录
如果数据表中存在自增主键、唯一 GUID 或其他可区分每一行数据的唯一列(本例中为 ID),我们可以采用“先保留,再剔除”的策略。通常的做法是:在每个重复组中,只保留最大或最小的那个唯一值对应的记录。
第一步:确认重复数据范围
执行以下查询,找出出现次数大于 1 的名称,以便观察待处理的对象:
SELECT Name
FROM Student
GROUP BY Name
HAVING COUNT(Name) > 1;
第二步:执行 DELETE 操作
通过嵌套子查询,筛选出属于重复组且其 ID 并非组内最大的记录,将其删除。具体逻辑如下:
- 外部条件:
WHERE Name IN (...)锁定重复的名称集合。 - 排除条件:
AND ID NOT IN (SELECT MAX(ID) ...)确保每个重复组中的最大 ID 不被删除,从而保留最新/最早的一条数据。
DELETE FROM Student
WHERE Name IN (
SELECT Name
FROM Student
GROUP BY Name
HAVING COUNT(Name) > 1
)
AND ID NOT IN (
SELECT MAX(ID)
FROM Student
GROUP BY Name
HAVING COUNT(Name) > 1
);执行上述脚本后,再次查询整表数据以验证结果:
风险提示:在执行删除操作前,建议先使用 SELECT 语句模拟结果,或开启事务以便在意外发生时回滚。
方法二:无唯一列时使用 ROW_NUMBER() 函数
当表中没有类似主键的唯一列来区分相同的行时,无法单纯依赖逻辑比较。此时,SQL Server 的窗口函数 ROW_NUMBER() 成为最佳选择,它能为每一行生成一个序列号,从而精准标记出多余的副本。
第一步:重新测试无唯一列场景
假设我们向表中插入了完全相同的数据,导致即使使用之前的逻辑也无法准确识别哪一行该留。例如插入一组无特征差异的记录:
-- 为了演示,这里假设有一组难以通过唯一值区分的重复行
第二步:构造 CTE 并删除序号大于 1 的行
核心思路是利用 CROSS APPLY 或在 CTE 中配合 ROW_NUMBER() 生成编号,然后删除编号大于 1 的记录:
DELETE T
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [ID]) AS RowNumber,
*
FROM Student
) T
WHERE T.RowNumber > 1;语法解析:
PARTITION BY [Name]:按照姓名字段将数据划分为多个分区。ORDER BY [ID]:在每个分区内部,依据ID进行排序(升序)。ROW_NUMBER():返回分区内每行的顺序序号,从 1 开始递增。同一分区内的序号互不重复。
执行该删除命令后,原本重复的姓名仅剩第一条(按 ID 最小排):
总结
处理数据库重复数据时,优先检查是否存在唯一标识列。若有,采用聚合极值法逻辑直观且开销小;若无,则借助 ROW_NUMBER() 提供的全局行号进行过滤。无论使用哪种方式,涉及破坏性操作(DELETE/DROP)之前,务必做好数据备份,防止误删核心信息。
以上就是 SQL Server 删除表中重复数据的详细内容,更多关于 SQL Server 数据清洗的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













