it编程 > 数据库 > MsSqlserver

SQL Server删除重复数据的核心方案

9人参与 2026-01-31 MsSqlserver

一、引言

在日常数据库运维与开发工作中,数据重复是高频出现的问题之一。尤其对于新闻类业务场景,news表中可能因接口重复调用、数据同步异常等原因,产生url相同但发布时间(publishtime)不同的重复记录。这类重复数据会占用额外存储资源,还可能导致前端展示错乱、统计分析失真等问题。

本文将针对sql server数据库,解决“删除news表中url重复数据,仅保留publishtime最大(最新发布)记录”的核心需求,提供一套高效、安全的单条sql实现方案,并深入解析其底层逻辑、扩展场景适配及关键注意事项,助力开发者快速落地业务需求。

二、核心需求与环境说明

2.1 需求拆解

2.2 环境适配

本方案基于sql server原生语法实现,兼容sql server 2008及以上所有版本,无需依赖第三方工具或插件,可直接在ssms、dbeaver等数据库客户端执行。

三、核心实现方案(单条sql搞定)

解决该需求的最优方案是「cte(公用表表达式)+ 窗口函数」组合,该方案逻辑清晰、执行高效,且能通过“先预览后删除”的方式保障数据安全。以下分两步展开,建议先执行预览语句确认无误后,再执行删除操作。

3.1 第一步:预览待删除的重复记录(关键!避免误删)

在执行删除操作前,务必先查询出待删除的记录,确认是否符合预期。sql语句如下:

-- 预览:查询url重复且非publishtime最大的记录(待删除数据)
with newscte as (
    select 
        id,
        url,
        publishtime,
        -- 按url分组,组内按publishtime降序排序,生成连续行号
        row_number() over (partition by url order by publishtime desc) as rn
    from news
)
select id, url, publishtime from newscte where rn > 1;

3.2 第二步:执行删除操作(单条sql完成)

确认预览结果无误后,执行以下sql语句,直接删除重复记录(仅保留每个url下publishtime最大的记录):

-- 最终删除语句:删除url重复数据,保留publishtime最大的记录
with newscte as (
    select 
        -- 仅需生成行号,无需查询所有字段,提升执行效率
        row_number() over (partition by url order by publishtime desc) as rn
    from news
)
delete from newscte where rn > 1;

四、核心逻辑深度解析

上述方案的核心在于cte与窗口函数的结合,我们逐句拆解逻辑,帮助大家理解其底层原理:

4.1 cte(公用表表达式)的作用

newscte是一个临时的结果集,用于存储对news表处理后的中间数据(此处主要是生成的行号rn)。cte的优势在于简化sql语句结构,避免重复编写子查询,同时让逻辑更易读,尤其适合复杂的分组排序场景。

4.2 窗口函数row_number()的核心作用

窗口函数(也叫分析函数)的核心是“分组排序并生成标识”,此处用到的row_number()函数语法解析如下:

row_number() over (partition by url order by publishtime desc) as rn

4.3 删除逻辑的闭环

通过上述处理后,每个url分组内:

因此,delete from newscte where rn > 1 语句会精准删除所有重复记录,仅保留每个url对应的最新发布记录,实现需求目标。

五、扩展场景适配(应对复杂业务需求)

实际业务中,可能存在更复杂的场景(如publishtime相同),我们基于核心方案进行扩展,满足多样化需求。

5.1 场景1:同一url+同一publishtime,保留id最大的记录

若存在“同一url、同一publishtime”的多条重复记录(即发布时间完全一致),此时仅按publishtime排序无法区分唯一记录,可叠加id字段(主键,唯一)排序,保留id最大的记录:

with newscte as (
    select 
        row_number() over (
            partition by url 
            order by publishtime desc, id desc  -- 先按时间降序,再按id降序
        ) as rn
    from news
)
delete from newscte where rn > 1;

5.2 场景2:保留publishtime最小的记录(反向需求)

若需求变为“删除重复url记录,保留最早发布(publishtime最小)的记录”,仅需将排序规则改为升序(asc,可省略不写):

with newscte as (
    select 
        row_number() over (partition by url order by publishtime asc) as rn
    from news
)
delete from newscte where rn > 1;

六、关键注意事项(生产环境必看)

删除操作属于高危操作,尤其在生产环境中,必须严格遵守以下 注意事项,避免数据丢失或业务异常:

6.1 先预览,后删除

务必先执行3.1节的预览语句,确认待删除的记录数量、内容与预期一致。若直接执行删除语句,一旦误删(如分组字段写错、排序方向错误),恢复数据成本极高。

6.2 执行前做好数据备份

对于生产环境的news表,建议在执行删除操作前,进行全量备份或增量备份。备份语句示例(完整备份):

backup database [你的数据库名] to disk = 'd:\backup\news_backup.bak' with init;

6.3 大数据量场景下的索引优化

若news表数据量较大(百万级及以上),直接执行窗口函数可能会因全表扫描导致执行效率低下。建议为url和publishtime建立联合索引,提升分组和排序的执行速度:

-- 建立联合索引:url(分组字段)+ publishtime(排序字段,降序)
create index ix_news_url_publishtime on news(url, publishtime desc);

索引创建后,窗口函数可通过索引快速定位分组和排序数据,执行效率可提升50%以上(具体视数据量而定)。

6.4 避免并发场景下的操作冲突

若news表存在高并发写入(如实时同步新闻数据),建议在执行删除操作时,通过事务或锁机制避免并发冲突,防止删除过程中新增重复数据或影响正常业务写入:

-- 开启事务,确保删除操作原子性
begin transaction;

with newscte as (
    select 
        row_number() over (partition by url order by publishtime desc) as rn
    from news with (updlock, holdlock)  -- 加锁,防止并发修改
)
delete from newscte where rn > 1;

-- 确认无误后提交事务,否则回滚
commit transaction;
-- rollback transaction;

七、总结

本文针对sql server中news表的重复数据删除需求,提供了“cte+窗口函数”的单条sql高效实现方案,核心优势的在于:

最后再次强调:删除数据前务必做好预览和备份,生产环境需谨慎操作。若你在实际落地过程中遇到其他复杂场景(如多字段去重、关联表去重),可基于本文核心逻辑进行扩展。

以上就是sql server删除重复数据的核心方案的详细内容,更多关于sql server删除重复数据的资料请关注代码网其它相关文章!

(0)

您想发表意见!!点此发布评论

推荐阅读

SQL中的UNION ALL和UNION 区别及如何使用

01-31

PostgreSQL向量检索之pgvector入门实战指南

01-31

PostgresSQL安装教程及初始使用操作方法

01-31

KingbaseES金仓数据库:ksql 命令行从建表到删表实战(含增删改查)

01-31

PostgreSQL索引的设计原则和最佳实践

01-27

使用Nginx和内网穿透实现多个本地Web站点的公网访问过程

01-31

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论