每天1个Linux运维操作小技巧2️⃣

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

mysql偶尔误操作导致数据重复,譬如用户信息表,user_info,前端登录时后台会查询出多条记录,从而导致登录失败

  • 解决思路:先查出重复的关键字段 mobile
    • Select mobile From user_info Group By mobile Having Count(1)>1;
查看是否有重复的数据:
GROUP BY <列名序列>
HAVING <组条件表达式>
查询出:根据dname分组,同时满足having字句中组条件表达式(重复次数大于1)的那些组
count(*)与count(1)其实没有什么差别,用哪个都可以;
复制代码
  • 再查出所有重复的数据

    • select *from user_info where mobile in (Select mobile From user_info Group By mobile Having Count(1)>1);
  • 然后将select 改成 delete,删除重复的数据,如果成功是删除所有重复的数据,

    • 但是上面的sql会出错:[Err] 1093 - You can't specify target table 'dept' for update in FROM clause
原因是:更新这个表的同时又查询了这个表,查询这个表的同时又去更新了这个表,可以理解为死锁。mysql不支持这种更新查询同一张表的操作
复制代码
  • 解决办法:把要更新的几列数据查询出来做为一个第三方表,然后筛选更新。
    • select *from user_info where mobile in (Select t.mobile From ( select mobile from user_info Group By mobile Having Count(1)>1 ) t );
但是这样,上面的sql删除了所有重复的数据,并没有留下一行,so,跟预期不符,还需要过滤一层,排除重复数据中的id或者user_id最小的一行(即寻找有差异的一个字段进行过滤);
select *from user_info where mobile in (Select mobile From user_info Group By mobile  Having Count(1)>1) and user_id not in (Select min(user_id) From user_info Group By mobile  Having Count(1)>1);
复制代码
  • 还有问题,上面的这种查询效率太低
根据重复字段mobile分组,查找出user_id最小的。然后再查找mobile不包含刚才查出来的。这样就查询出了所有的重复数据(除了user_id最小的那行):
select *from user_info where user_id not in (select  dt.minno from (select min(user_id) as minno from user_info group by mobile HAVING COUNT(1)>1 ) dt );
复制代码
  • 上面的sql有毛病,请谨慎执行!查出最小的id,not in,那么要删除的就不能是最小的id数据,会将很多数据清空删掉,so,是要删除的就是查询出来的最大或最小的id,in即可;当前mysql版本不支持in操作

猜你喜欢

转载自juejin.im/post/7018479022032027679