刚开始,根据我的想法,这个很简单嘛,上sql语句
delete from zqzrdp where tel in (select min(dpxx_id) from zqzrdp group by tel having count(tel)>1);
执行,报错!!~!~
异常意为:你不能指定目标表的更新在FROM子句。傻了,MySQL 这样写,不行,让人郁闷。
难倒只能分步操作,蛋疼
以下是网友写的,同样是坑爹的代码,我机器上运行不了。
1. 查询需要删除的记录,会保留一条记录。
select a.id,a.subject,a.RECEIVER from test1 a left jo
在MySQL数据库管理中,删除重复数据是一个常见的需求,特别是在数据清洗和数据整理的过程中。然而,直接使用简单的SQL语句往往无法解决这个问题,因为MySQL对于某些特定的更新操作有限制。以下是一些删除数据库中重复数据的方法,这些方法适用于不同的场景。
1. **删除基于单一字段的重复数据**:
- 可以使用`GROUP BY`和`HAVING`子句找到重复的记录,例如:
```sql
SELECT peopleId FROM people GROUP BY peopleId HAVING COUNT(peopleId) > 1;
```
- 然后,通过`NOT IN`子句和`MIN(rowid)`选择保留最小`rowid`的记录:
```sql
DELETE FROM people WHERE peopleId IN (...) AND rowid NOT IN (SELECT MIN(rowid) FROM people GROUP BY peopleId HAVING COUNT(peopleId) > 1);
```
2. **删除基于多字段的重复数据**:
- 类似地,如果需要基于多个字段判断重复,可以将多个字段放在`GROUP BY`子句中:
```sql
DELETE FROM vitae a WHERE (a.peopleId, a.seq) IN (...);
```
这里`IN`子句内的查询与上述单字段删除操作类似,只是需要同时考虑`peopleId`和`seq`。
3. **使用临时表进行处理**:
- 当无法直接删除重复数据时,一种常见的解决方案是创建临时表。创建一个临时表,存储每个唯一组合的最小`autoID`:
```sql
CREATE TABLE tmp SELECT MIN(autoID) AS autoID FROM tableName GROUP BY Name, Address;
```
- 然后,将原表数据复制到临时表,只保留匹配`autoID`的记录:
```sql
CREATE TABLE tmp2 SELECT tableName.* FROM tableName, tmp WHERE tableName.autoID = tmp.autoID;
```
- 删除原表并重命名临时表为原表名:
```sql
DROP TABLE tableName;
RENAME TABLE tmp2 TO tableName;
```
4. **利用索引来提升性能**:
- 在执行删除操作之前,确保用于判断重复的字段有索引,如`subject`和`RECEIVER`,这可以显著提高查询和删除的速度。
5. **注意MySQL的限制**:
- MySQL不允许在一个`DELETE`语句中直接引用被删除的表。因此,像`DELETE FROM zqzrdp WHERE tel IN (SELECT ...)`这样的语句是不被允许的,必须采用其他方法绕过这个限制。
6. **并发控制与数据安全**:
- 在处理大量数据或并发环境时,可能需要使用锁表机制来确保数据一致性。例如,在Yii框架中,可以通过锁表来防止并发情况下出现重复数据。
7. **避免全表扫描**:
- 使用`JOIN`和`IN`子句时,应尽量减少全表扫描,避免对大表造成性能影响。如果数据量巨大,可以考虑分批处理。
8. **数据备份**:
- 在进行任何数据清理操作之前,都应备份数据,以防意外丢失重要信息。
总结来说,删除MySQL中的重复数据需要综合运用各种SQL技巧,包括但不限于`GROUP BY`、`HAVING`、`JOIN`、`IN`、`NOT IN`以及临时表等。理解这些概念并根据实际场景灵活应用是解决此类问题的关键。同时,务必确保在执行删除操作前进行充分的测试和数据备份,以保障数据的安全。