统计SQL重复数据需先明确重复逻辑:整行重复或字段组合重复;常用GROUP BY+COUNT()筛选重复组,窗口函数ROW_NUMBER()标记重复序号以定位具体记录,自连接可直观展示重复ID对。

要统计和定位SQL中的重复数据,核心是利用分组聚合与窗口函数,结合主键或唯一标识判断冗余记录。关键不在于删数据,而在于先看清重复逻辑——是整行重复,还是某几列组合重复。
按字段组合统计重复次数
最常用方法是用 GROUP BY 配合 COUNT(),筛选出现次数大于1的分组:
-
查出哪些“姓名+手机号”组合重复了,并统计次数:
SELECT name, phone, COUNT(*) AS cnt
FROM users
GROUP BY name, phone
HAVING COUNT(*) > 1; - 注意:GROUP BY 的字段必须和 SELECT 中的非聚合字段完全一致;HAVING 用于过滤分组结果,不能用 WHERE。
查出所有重复行的具体记录(含ID)
仅知道哪组重复还不够,常需看到每条重复数据的完整信息(比如ID),方便后续核对或清理:
-
用窗口函数 ROW_NUMBER() 标记重复序号:
SELECT id, name, phone,
ROW_NUMBER() OVER (PARTITION BY name, phone ORDER BY id) AS rn
FROM users
WHERE (name, phone) IN (
SELECT name, phone FROM users GROUP BY name, phone HAVING COUNT(*) > 1
); - 结果中 rn > 1 的行即为重复副本(rn = 1 可视为“首条保留项”)。
- 支持按时间、ID等排序决定“保留谁”,灵活可控。
快速识别整行完全重复(无主键/无业务键场景)
当表没有明确唯一约束,又怀疑存在完全相同的行时,可借助所有列参与分组(需注意NULL处理):
-
把所有字段放进 GROUP BY(推荐先确认字段列表):
SELECT *, COUNT(*) AS cnt
FROM orders
GROUP BY order_no, user_id, amount, create_time, status
HAVING COUNT(*) > 1; - 若字段多且含 NULL,建议用 COALESCE 处理,例如
COALESCE(status, 'unknown'),避免NULL被当作不同值。
用自连接定位重复记录ID对
适合小到中等数据量,直观展示“谁和谁重复”,便于人工比对:
-
找出同一手机号下所有ID两两配对(排除自匹配):
SELECT a.id AS id1, b.id AS id2, a.phone
FROM users a
INNER JOIN users b ON a.phone = b.phone AND a.id - a.id










