MySQL单表去重案例

解决MySQL唯一约束添加失败

问题描述:线上数据库表字段需要添加一个唯一约束(之前该字段有索引)。添加的时候报错(下文操作均为测试环境问题复现)

root@localhost:mysql.sock  17:42:18 [practice]>drop index idx_name on test;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

root@localhost:mysql.sock  17:44:30 [practice]>alter table test add unique idx_name(name);
ERROR 1062 (23000): Duplicate entry 'eeee' for key 'idx_name'

root@localhost:mysql.sock  17:47:55 [practice]>delete from test where id in (SELECT t1.id from test as t1,test as t2 where t1.name = t2.name and t1.id !=t2.id);
ERROR 1093 (HY000): You can't specify target table 'test' for update in FROM clause

root@localhost:mysql.sock  18:04:14 [practice]>delete from test where id in (SELECT t1.id from (select * from test as tmp) as t1,(select * from test as tmp) as t2 where t1.name = t2.name and t1.id !=t2.id);
Query OK, 5 rows affected (0.01 sec)

纳尼?查下官方文档吧,看来是不支持这样搞(我的版本是5.7.14)

175557_YY8w_3023401.png

 

解决办法:

方案一:这个命令在MySQL5.1.37之前是可以的,在5.1.48以后就行不通了,它会删除重复数据,建立唯一索引。另外这个方式在percona server中也是行不通的(用不了)

alter ignore table test addunique idx_name (name);

方案二:重建表

创建一个中间表,对数据去重插入中间表,再drop原表,rename中间表

root@localhost:mysql.sock  18:37:56 [practice]>insert into uniq_test select * from test group by name;
Query OK, 6 rows affected (0.01 sec)
Records: 6  Duplicates: 0  Warnings: 0
root@localhost:mysql.sock  18:42:26 [practice]>drop table test;
root@localhost:mysql.sock  18:42:51 [practice]>rename table uniq_test to test;

方案三:利用中间表(推荐)

| tmp_ids | CREATE TABLE `tmp_ids` (
  `id` int(11) DEFAULT NULL,
  `name` char(20) DEFAULT NULL
) ENGINE=innodb DEFAULT CHARSET=utf8 |

root@localhost:mysql.sock  19:36:02 [practice]>insert into tmp_ids select max(id),name from test group by name having count(*)>1 orderr by null;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

root@localhost:mysql.sock  19:38:07 [practice]>delete a.* from test a,tmp_ids b where b.name=a.name and a.id<b.id;
Query OK, 2 rows affected (0.04 sec)

 

为了方便大家交流,本人开通了微信公众号,和QQ群291519319。喜欢技术的一起来交流吧

转载于:https://my.oschina.net/u/3023401/blog/912816

### MySQL操作的实现方式 在 MySQL 数据库中,`DISTINCT` 和 `GROUP BY` 是两种常用的方法。以下是它们的具体用法以及性能上的差异。 #### 使用 DISTINCT 实现 `DISTINCT` 关键字用于返回唯一的不同值。它通常应用于列或多列组合的结果集中复项。以下是一个简的例子: ```sql -- 查询 plan_number 列中的不复值 SELECT DISTINCT PLAN_NUMBER FROM psur_list; ``` 如果需要对多列进行,则可以指定多个字段作为参数[^3]: ```sql -- 对 plan_number 和 product_name 进行联合 SELECT DISTINCT PLAN_NUMBER, PRODUCT_NAME FROM psur_list; ``` #### 使用 GROUP BY 实现 `GROUP BY` 主要用于分组聚合操作,但它也可以用来掉某些维度下的复记录。当配合其他聚合函数一起使用时效果更佳。例如: ```sql -- 按照 songid 分组并统计每首歌的数量 SELECT SONGID, COUNT(*) AS NUM_SONGS FROM feedback GROUP BY SONGID; ``` 需要注意的是,在实际应用过程中可能会遇到错误提示,比如由于 SQL 语句书写不当引起的语法问题。如下面这个案例展示了因未正确定义排序依据而导致失败的情况[^2]: ```sql -- 错误示范:试图按不存在的新时间(new_time)降序排列 SELECT COUNT(*), SONGID FROM feedback GROUP BY SONGID ORDER BY NEW_TIME DESC; -- 此处会报错因为没有定义 new_time 字段 ``` 为了修复上述错误,应该确保所使用的字段名存在于当前结构或者已经被计算出来: ```sql -- 修改后的正确版本 SELECT COUNT(*), SONGID FROM feedback GROUP BY SONGID ORDER BY MAX(NEW_TIME) DESC; -- 假设 new_time 存在于反馈里 ``` #### 性能对比分析 尽管两者都能完成基本的数据清理任务,但在大规模数据集上运行效率可能存在显著区别。一般来说,`DISTINCT` 的执行速度较快因为它只简地过滤掉完全相同的行;而 `GROUP BY` 可能涉及更多的内部处理步骤尤其是当你附加额外的汇总运算符的时候。 然而具体哪个更快取决于具体的查询场景、索引状态以及其他因素。因此建议针对特定需求测试两者的效能现后再做决定。 --- ### 示例总结 通过上面的例子可以看出,无论是采用 `DISTINCT` 方法还是利用 `GROUP BY` 来达到目的各有优劣之处。对于纯想要获取无冗余列的情形下推荐优先考虑前者;而对于那些还需要进一步加工统计数据的需求则后者更为合适一些。 ```sql -- Example with DISTINCT SELECT DISTINCT COLUMN_NAME FROM TABLE_NAME; -- Example with GROUP BY and aggregate function SELECT CATEGORY_COLUMN, SUM(VALUE_COLUMN) FROM TABLE_NAME GROUP BY CATEGORY_COLUMN; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值