MySQL技术问询:如何删除字段重复项及带前缀的对应重复行
没问题,这两个关于MySQL删除重复记录的问题我经常遇到,给你详细拆解一下:
1. 在MySQL中如何删除某一字段的重复记录?
核心需求一般是保留重复组里的某一条记录(比如最早/最晚创建的),删掉其他重复项,这里有两种常用方案,适配不同MySQL版本:
- 方案一:DELETE自连接(兼容所有MySQL版本)
假设你的表叫your_table,要去重的字段是target_column,我们要保留每个重复组里id最小的那条(你也可以换成其他唯一标识字段,比如创建时间create_time):
DELETE t1 FROM your_table t1 JOIN your_table t2 ON t1.target_column = t2.target_column AND t1.id > t2.id;
简单说就是:通过自连接找到所有和其他行字段值相同,但id更大的行,然后删掉这些行——这样就留下了每个重复组里id最小的那条。如果想保留id最大的,把t1.id > t2.id改成t1.id < t2.id就行。
- 方案二:窗口函数(MySQL 8.0+适用)
如果你的MySQL是8.0及以上版本,用窗口函数会更直观,逻辑清晰不容易出错:
DELETE FROM your_table WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY target_column ORDER BY id) AS rn FROM your_table ) AS temp WHERE rn > 1 );
这里用ROW_NUMBER()给每个target_column相同的行分组编号,编号大于1的就是重复项,直接删掉就行。注意必须套一层子查询,因为MySQL不允许在DELETE语句里直接引用正在修改的表,临时表刚好规避这个问题。
2. 在MySQL中是否可以删除与另一行字段带有指定前缀的对应重复行?
当然可以!关键是先明确“对应重复”的逻辑,我给你两种最常见的场景举例:
场景一:删除前缀相同且字段值完全重复的行
比如你的表有个value字段,前缀是pre_,要删掉所有value以pre_开头且重复的行,只保留每个值的一条:
直接在上面的去重逻辑里加个前缀过滤条件就行:
-- 用DELETE自连接的方式 DELETE t1 FROM your_table t1 JOIN your_table t2 ON t1.value = t2.value AND t1.id > t2.id WHERE t1.value LIKE 'pre_%';
或者用窗口函数的版本:
DELETE FROM your_table WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY value ORDER BY id) AS rn FROM your_table WHERE value LIKE 'pre_%' ) AS temp WHERE rn > 1 );
这样就只会处理带pre_前缀的行,不会影响其他前缀的记录。
场景二:删除去掉前缀后内容重复的行
比如value字段是pre_apple、pre_apple、other_apple,你要删的是去掉pre_前缀后内容重复的行(也就是apple重复的那些pre_开头的行),这时候需要先提取前缀后的内容:
- 如果前缀是固定长度的(比如
pre_是4个字符),用SUBSTRING():
DELETE t1 FROM your_table t1 JOIN your_table t2 ON SUBSTRING(t1.value, 5) = SUBSTRING(t2.value, 5) -- 从第5个字符开始取,去掉pre_ AND t1.id > t2.id WHERE t1.value LIKE 'pre_%';
- 如果前缀是不固定长度但有分隔符(比如
_),用SUBSTRING_INDEX()取分隔符后面的内容:
DELETE t1 FROM your_table t1 JOIN your_table t2 ON SUBSTRING_INDEX(t1.value, '_', -1) = SUBSTRING_INDEX(t2.value, '_', -1) -- 取_后面的部分 AND t1.id > t2.id WHERE t1.value LIKE 'pre_%';
这样就能精准删掉符合要求的重复行啦。
内容的提问来源于stack exchange,提问作者d-_-b




