MySQL 如何查找并删除重复记录

直接说,查重复记录就是用GROUP BY和HAVING,删除重复的用DELETE结合JOIN或子查询。

1 . 查重复:
单字段重复:SELECT email, COUNT(email) FROM people GROUP BY email HAVING COUNT(email) > 1 ;
多字段重复:SELECT FROM people WHERE (name, email) IN (SELECT name, email FROM people GROUP BY name, email HAVING COUNT(1 ) > 1 ) ORDER BY email;
2 . 删除重复:
删除最大ID记录:DELETE p FROM people p JOIN people d ON p.email = d.email AND p.id < d>删除最小ID记录:DELETE p FROM people p JOIN people d ON p.email = d.email AND p.id > d.id;
使用子查询:DELETE FROM people WHERE id NOT IN (SELECT MIN(id) FROM people GROUP BY email);
使用中间表:创建临时表,保留最小ID数据,然后删除原表,最后重命名临时表。

MySQL 8 .0以上还可以用窗口函数: DELETE FROM people WHERE id IN (SELECT id FROM (SELECT id, ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS row_num FROM people) d WHERE row_num > 1 );
你自己看哪种适合你。

数据库mysql怎么删除重复项

嘿,哥们儿,我之前就干过这么个活儿。
记得那会儿,我们公司数据库里的客户信息表,邮箱地址重复的简直跟什么似的。
那数据,看着就头疼。

先说确定重复项的列吧,那可不容易。
我那时候是花了半天时间,翻来覆去地检查,最后确定就盯着email这一列。
你看,客户信息表里,邮箱地址是唯一的标识,重复了就麻烦了。

然后呢,我就用那个DISTINCT和GROUP BY来查询重复项。
这玩意儿其实很简单,我那时候就那么写:
sql SELECT DISTINCT email FROM customers; SELECT email, COUNT() FROM customers GROUP BY email HAVING COUNT() > 1 ;
结果出来一看,哎呀妈呀,好几个重复的邮箱地址。
接着,我就开始动手删了。

删除重复项的时候,我用的那个自连接的方法,挺管用的。
具体操作就是:
sql DELETE t1 FROM customers t1 INNER JOIN customers t2 WHERE t1 .email = t2 .email AND t1 .customer_id > t2 .customer_id;
这里头,t1 和t2 是表别名,通过自连接找到重复的项。
customer_id这个字段,我默认是主键,所以按照这个字段来保留一条记录,其他的就删了。

关键是要注意,操作之前得备份,免得万一搞错了,数据就没了。
还有,操作时间选个低峰期,别高峰期一忙,出点啥岔子就不好了。

最后,我还想说一句,这事儿得谨慎,尤其是对于那种经常更新的表,最好用事务,加上索引,这样性能会好一点。

哦,对了,我还试过用临时表的方法,感觉挺安全的。
就是先创建个临时表,把唯一的数据放进去,然后再替换原表。
不过这个方法比较复杂,一般用自连接的方法就够用了。

如何从 MySQL 数据库中删除重复数据

说实话,这事儿吧,得一步步来。
先说说怎么找重复的。

你想找MySQL里重复的记录,对吧?比如员工表employees,你想看first_name、last_name和email这三个字段是不是有一样的。
咋办?用SQL查。

sql SELECT first_name, last_name, email, COUNT() FROM employees GROUP BY first_name, last_name, email HAVING COUNT() > 1 ;
这个查询是啥意思?就是把所有员工按这三个字段分组,然后数数每组有多少人。
如果某个组合的人数大于1 ,说明有重复的。
比如,你发现有两个张三,名字和email都一样。

找到了重复的,下一步就得删掉。
有俩办法。

方法一:自连接
这个方法挺有意思。
你把employees表跟自己连起来,但只连那些first_name、last_name、email都一样的行。
然后呢,你让SQL只删掉那些id比其他同组记录大的行,留最小的那个。

sql DELETE e1 FROM employees e1 JOIN employees e2 ON e1 .first_name = e2 .first_name AND e1 .last_name = e2 .last_name AND e1 .email = e2 .email AND e1 .id > e2 .id;
这查询是啥意思?就是找所有重复的人,但每个组里只留id最小的,其他的都删掉。
比如,有两个张三,一个id是1 ,一个id是2 ,email、name都一样。
这个查询就会删掉id为2 的那个。

方法二:临时表
有时候,你可能想保留最新的那个记录,或者工资最高的那个。
这时候自连接就不够用了。
你可以先建个临时表,存下你想保留的那些记录。

sql CREATE TEMPORARY TABLE temp_employees AS SELECT FROM employees e1 WHERE e1 .id IN ( SELECT MIN(id) FROM employees GROUP BY first_name, last_name, email );
这临时表是啥?就是每个重复组里id最小的那个记录。
然后呢,你再用个删除查询,删掉所有不在临时表里的记录。

sql DELETE FROM employees WHERE id NOT IN (SELECT id FROM temp_employees);
这查询是啥意思?就是删掉所有那些id不在临时表里的记录。
比如,你用临时表存了每个重复组里id最小的那个,那其他重复的记录就都被删掉了。

防止未来重复
找到了,删掉了,但咋保证以后不会再有重复呢?加个唯一约束呗。

sql ALTER TABLE employees ADD CONSTRAINT unique_employee UNIQUE (first_name, last_name, email);
这约束是啥?就是告诉MySQL,first_name、last_name、email这三个字段组合起来必须是唯一的。
你要是尝试插入重复的,MySQL就会报错。

性能优化
处理大数据的时候,这事儿还是挺耗资源的。

索引:给那些你用来找重复的列加索引。
比如first_name、last_name、email。
索引能加快查询速度。
你可以用这个命令建索引:
sql CREATE INDEX idx_employee ON employees (first_name, last_name, email);
批量删除:如果你表里有成千上万条重复的记录,一次性全删可能把服务器搞垮。
这时候你就得分批删。
比如,你每次删1 000条。

sql DELETE e1 FROM employees e1 JOIN employees e2 ON e1 .first_name = e2 .first_name AND e1 .last_name = e2 .last_name AND e1 .email = e2 .email AND e1 .id > e2 .id LIMIT 1 000; 这查询是啥意思?就是每次删1 000条重复的记录。
你得跑好几次这个查询,直到所有重复的都被删完。

就这些了。
找、删、防止再发生,还有咋优化。
具体用哪个方法,看你的需求。
有时候自连接挺好,有时候临时表更合适。
关键是先搞明白你的数据,再选对方法。