Mysql删除重复数据通用SQL

Mysql删除重复数据的SQL解决策略
本文分享了两种处理Mysql数据库中因bug导致的数据重复问题的通用SQL删除重复数据的方法,包括使用INNERJOIN和EXISTS子句的写法,以及如何基于特定字段(column_1和column_2)进行分组和删除规则。

在日常开发过程中,可能会出现一些 bug,导致 Mysql 数据库数据重复,需要删除重复数据,这里记录下删除重复数据的通用 SQL ,方便以后需要时查阅

1、写法一

DELETE t1
FROM
	tbl_name t1
INNER JOIN tbl_name t2
WHERE
	t1.id < t2.id
AND t1.column_1 = t2.column_1
AND t1.column_2 = t2.column_2;

2、写法二

DELETE
FROM
	tbl_name
WHERE
	EXISTS (
		SELECT
			*
		FROM
			(
				SELECT
					max(id) AS id,
					column_1,
					column_2
				FROM
					tbl_name
				GROUP BY
					column_1,
					column_2
				HAVING
					count(1) > 1
			) t
		WHERE
			tbl_name.column_1 = t.column_1
		AND tbl_name.column_2 = t.column_2
		AND tbl_name.id < t.id
	)

重复数据中,保留 id 最大的,其余都删除,SQL 中 tbl_name 表示需要删除重复数据的表名,column_1column_2 是用来分组确认重复数据的字段。

<think>好的,我现在需要帮助用户解决在MySQL删除重复数据但保留一条的问题。首先,我得回忆一下用户提供的引用内容,看看有没有相关的解决方案。根据引用[1]和引用[2],他们提到当表中存在完全相同的行时,可以使用DELETE语句配合LIMIT子句来删除重复项。但要注意,这种方法可能在有主键的情况下不太适用,因为主键不同,但其他列可能重复。 用户的需求是删除重复行,仅保留一条。我需要先确定如何识别重复行,以及如何安全地删除它们,同时避免死锁问题,引用[3]提到删除操作可能导致死锁,所以需要注意这一点。 首先,常见的方法通常包括使用临时表或者利用唯一标识来删除重复数据。如果表中没有主键或唯一索引,可能需要添加一个临时列来辅助处理。例如,使用ALTER TABLE添加自增ID,然后删除ID较大的重复行。这种方法可以确保每个重复组只保留一条记录,通常是ID最小的那条。 另一种方法是使用子查询来找到重复的行,然后使用DELETE JOIN语句删除多余的记录。比如,通过自连接表,比较相同数据但主键不同的行,然后删除其中主键较大的行。这种方法需要确保每组的重复数据有一个可以比较的字段,比如自增ID。 此外,用户可能需要考虑使用窗口函数,比如ROW_NUMBER(),这在MySQL 8.0及以上版本支持。通过为每个重复组分配行号,然后删除行号大于1的记录。这种方法更现代,但需要确认用户使用的MySQL版本是否支持。 需要注意的是,在执行删除操作前,务必备份数据,防止误删。同时,处理大量数据时,可能需要分批次操作,避免锁表时间过长,引用[3]提到的死锁问题,可能需要优化事务处理或调整隔离级别。 总结可能的步骤:1. 识别重复数据;2. 确定保留哪一条(如最小ID);3. 使用DELETE语句删除其他重复项。或者创建临时表,复制唯一数据后替换原表。这两种方法各有利弊,临时表方法更安全但需要更多存储空间,DELETE直接操作更快但有风险。 另外,用户可能需要处理部分列重复的情况,这时候需要根据具体列来定义重复,并在WHERE子句中指定这些列。例如,使用GROUP BY指定重复的列,然后保留MIN(id)的记录。 最后,确保提供的解决方案示例代码正确,比如使用DELETE ... WHERE ... IN (SELECT ...)时,MySQL可能不允许在子查询中直接引用要删除的表,这时候需要用嵌套子查询或者临时表来绕过限制。</think>### MySQL删除重复数据保留一条的解决方案 #### 1. 核心思路 在MySQL删除重复数据需要三个步骤:**定义重复规则** → **标记保留行** → **删除多余行**。这里提供三种通用方法,适用于不同版本的MySQL,均需注意操作前备份数据[^1][^2]。 --- #### 2. 具体实现方案 ##### 方法一:使用临时表(推荐) ```sql -- 创建临时表存储唯一数据 CREATE TABLE tmp_table LIKE your_table; -- 插入需要保留的数据(保留每组重复数据的最小ID) INSERT INTO tmp_table SELECT * FROM your_table WHERE id IN ( SELECT MIN(id) FROM your_table GROUP BY col1, col2, col3 -- 定义重复列 ); -- 替换原表 RENAME TABLE your_table TO old_table, tmp_table TO your_table; -- 删除旧表 DROP TABLE old_table; ``` ##### 方法二:直接删除MySQL 8.0+) ```sql DELETE FROM your_table WHERE id NOT IN ( SELECT * FROM ( SELECT MIN(id) FROM your_table GROUP BY col1, col2, col3 -- 定义重复列 ) AS keep_ids ); ``` ##### 方法三:自连接删除 ```sql DELETE t1 FROM your_table t1 INNER JOIN your_table t2 WHERE t1.id > t2.id -- 保留较小ID AND t1.col1 = t2.col1 -- 定义重复列 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3; ``` --- #### 3. 性能对比表 | 方法 | 优点 | 缺点 | 适用场景 | |------------|---------------------|-----------------------|--------------------| | 临时表法 | 安全可靠,避免死锁[^3] | 需要双倍存储空间 | 大数据量或关键数据 | | 直接删除法 | 单步完成操作 | 可能触发表锁 | MySQL 8.0+版本 | | 自连接删除 | 无需临时表 | 需自增ID字段 | 中小规模数据 | --- #### 4. 关键注意事项 1. **定义重复规则**:需明确哪些列组合视为重复(如`(name,email)`组合) 2. **数据备份**:建议先执行`CREATE TABLE backup_table AS SELECT * FROM your_table` 3. **死锁预防**:使用`LIMIT 1000`分批次删除,例如: ```sql DELETE FROM your_table WHERE id IN (duplicate_ids) LIMIT 1000; -- 分批次执行[^3] ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步亿点点的小码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值