SQL如何快速找出重复数据并编号 ROW_NUMBER去重技巧
SQL如何快速找出重复数据并编号 ROW_NUMBER去重技巧

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
用 ROW_NUMBER() 给重复行打序号,再筛出重复组
开门见山,先说一个核心结论:ROW_NUMBER() 这个窗口函数本身并不具备“去重”的魔法,它的核心任务仅仅是编号。真正的去重操作,需要你配合子查询或者公共表表达式(CTE),把那些编号为1(或者大于1)的行精准地筛选出来。整个过程的关键,首先在于明确定义“究竟依据哪些字段来判断重复”,然后通过 PARTITION BY 子句来分组编号。
一个新手常踩的坑,是写成 ROW_NUMBER() OVER (ORDER BY col) 这种形式。这会导致在全表范围内进行连续编号,根本没有进行分组,自然也就无法识别出哪些记录是彼此的“复制品”。
- 定义分组是关键:必须使用
PARTITION BY col1, col2来指定判定重复的字段组合,比如单一的email字段,或者复合的user_id, order_date。 - 组内排序求稳定:括号内的
ORDER BY只负责控制每个分组内部的排序逻辑。通常选用id或created_at这类具有唯一性或时间顺序的字段,以确保每次执行的结果都稳定一致。 - 编号逻辑要看清:编号从1开始,且在每个分组内独立计数。因此,对于重复的数据组,必然会出现
rn = 1(通常被视作保留行)和rn > 1(通常被视作待处理行)的记录。
查出所有重复记录(含编号),方便人工核对
这一步至关重要,却最容易被跳过:还没看清楚重复数据到底长什么样,就急着动手删除,很容易导致误删。更稳妥的做法是,先用CTE把编号结果封装起来,同时结合 COUNT(*) OVER (PARTITION BY ...) 窗口函数,直接计算出每组的记录条数。这样,数据状况便一目了然。
WITH duped AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS rn,
COUNT(*) OVER (PARTITION BY email) AS cnt
FROM users
)
SELECT * FROM duped WHERE cnt > 1;
这里需要特别注意两个筛选条件的区别:cnt > 1 用于筛选出“所有属于重复组”的行;而 rn = 1 则用于在重复组中“保留第一条”。在编写删除逻辑时,可千万别把这两个条件混淆了。
保留每组第一条,删掉其余重复行(安全删除写法)
直接执行 DELETE 语句风险较高,务必先进行数据备份或在事务中测试。此处的核心难点在于,如何让数据库精准定位“哪些行该被删除”。通常的做法是通过子查询关联原表的主键,而不是试图直接用 ROW_NUMBER() 的生成列进行删除(部分数据库不支持这种语法)。
- 语法因数据库而异:PostgreSQL / SQL Server / Oracle 等数据库支持
DELETE ... USING或DELETE FROM ... WHERE id IN (SELECT ...)这类写法。 - MySQL的版本差异:MySQL 8.0+ 版本可以优雅地使用 CTE 配合
DELETE,但老版本可能需要借助临时表或自连接来实现。 - 一种更通用的替代方案:
DELETE FROM users WHERE id NOT IN ( SELECT MIN(id) FROM users GROUP BY email );
这种使用GROUP BY和MIN()聚合函数的方法比ROW_NUMBER()更简洁,但它有一个局限:你无法灵活控制“保留哪一条”,只能依赖MIN()或MAX()这类聚合规则。
ROW_NUMBER() 和 DENSE_RANK() 在去重场景的区别
是不是有人尝试过用 DENSE_RANK() 来代替 ROW_NUMBER() 进行去重,却发现编号结果“不对劲”?原因在于,去重逻辑依赖于“组内是否能为每行生成唯一的序号”,而 DENSE_RANK() 函数会对相同的排序值赋予相同的排名,这导致它无法有效区分同一分组内的不同行。
ROW_NUMBER():在组内生成严格的 1, 2, 3… 序列。这让我们可以精准定位“第一条”和“非第一条”记录,是去重场景的理想选择。RANK()或DENSE_RANK():当遇到相同的ORDER BY值时,会产生并列排名(例如 1, 1, 3 或 1, 1, 2)。这种情况下,你无法简单地用rn = 1来安全地保留唯一的一行。- 从性能角度看,这几个函数差异不大,但语义清晰度天差地别。所以,别为了省事而随意替换函数。
话说回来,真正棘手的往往不是SQL怎么写,而是“重复”这个定义本身是否合理。举个例子,忽略空格、大小写或时区偏移的邮箱地址,到底算不算重复?这些问题必须在 PARTITION BY 之前就处理好,比如使用 TRIM(LOWER(email)) 进行标准化。否则,后续的编号分组从一开始就错了,再精巧的语法也是徒劳。
相关攻略
关于karrigan转会至Falcons 知名主持人BanKs在最新一期的播客《All About Counter-Strike》中,深入剖析了karrigan转会至Falcons的幕后逻辑,其中的观点值得玩味。 先看一个基本事实:karrigan已经36岁了。这意味着,这次转会很可能成为他职业生涯
松下电吹风插电不转?别急着扔,九成可能是这个原因 家里的松下电吹风插上电后毫无反应,风扇纹丝不动,很多人第一反应是电机烧了,维修价值不大。但事实恰恰相反,绝大多数情况下,问题并非出在核心电机上,而是前端的供电链路出现了物理性中断。根据松下官方售后技术手册以及多家授权维修中心近三年的故障统计数据,像E
家用吸尘器完全适合清洁地毯,但效果高度依赖吸头设计与动力配置 先说一个核心判断:用家用吸尘器清洁地毯,这事儿完全可行,但效果好坏,关键得看装备和手法。如今,主流品牌像小熊、追觅这些,早就为地毯场景优化了产品。它们普遍配备了电动滚刷、拍打震动模块或是专用平板吸头,目的很明确——就是要松动并吸走那些死死
按摩椅力度调小后依然有效,关键在于匹配个体身体状态与使用需求 现代中高端按摩椅普遍配备多级力度调节系统,但很多人心里犯嘀咕:力度调小了,是不是就变成隔靴搔痒,没什么实际作用了? 事实恰恰相反。实测数据显示,轻柔档位(比如30%—50%的输出强度)在缓解日常肩颈僵硬、改善浅层血液循环方面,有着明确的生
PoE交换机好坏,普通测线仪说了不算 想用普通网线测线仪来判断一台PoE交换机的好坏?这个想法很危险。原因很简单:普通测线仪只能干些基础活儿,比如看看网线通不通、线序对不对、有没有短路断路。但对于PoE交换机的核心能力——供电电压是否达标、输出功率稳不稳定、是否兼容最新的IEEE标准、带载后电压会不
热门专题
热门推荐
Origin Code发布VORTEX系列专用分体式水冷冷头模块 2026年4月7日,知名内存模组品牌Origin Code正式发布了专为VORTEX系列内存打造的分体式水冷冷头模块,官方售价为899元。这款产品的推出,为追求极致散热性能、低温和系统视觉一体化的高端DIY玩家及超频爱好者,提供了一个
荣耀WIN游戏本定档4月23日:性能释放突破250瓦,电竞体验全面升级 2026年4月7日,荣耀正式揭晓了全新WIN游戏本的发布日期:4月23日。这款备受瞩目的产品其实早已不是秘密,早在去年12月,荣耀PC产品负责人就已经在公开渠道透露了新品的进展,并确认了一个关键身份——它将成为《三角洲行动》职业
内存供应趋紧,苹果部分Mac交付周期显著延长 进入2026年第二季度,全球半导体产能的重新分配仍在持续。一个不容忽视的趋势是,人工智能应用的爆发式增长,正持续推高对高性能内存芯片的需求,导致DRAM市场供应整体趋紧。自去年下半年开始的这轮价格上涨,让终端设备制造商普遍感受到了成本压力,即便是供应链管
荣威全新i6上市:7 49万起售,搭载8155芯片与国潮 2026年4月30日,荣威品牌旗下的全新一代紧凑型轿车i6正式推向市场。新车一口气带来了三款配置,分别命名为长久版、豪久版与臻久版,官方给出的指导价区间定在7 49万元到8 49万元。不过,眼下正值上市初期,官方还推出了限时抢订政策,实际支付
暗黑破坏神4:憎恨之王上线后,术士职业迅速跻身当前版本最具统治力的职业行列 其核心能力涵盖恶魔召唤、地狱火攻击与神秘印记体系,其中一种以“召唤即献祭”为运转逻辑的召唤流派正展现出显著优势。 这次资料片带来的技能系统重构,可以说是一次彻底的革新:所有被动技能被移除,每个主动技能都扩展成了拥有多节点分支





