用SQL语句删除数据库重复数据,只保留一条有效数据

在实际开发中,可能会遇到数据库多条数据重复了,此时我们需要删除重复数据,只保留一条有效数据,用SQL语句怎么实现呢,下面我们模拟一下:

1.准备重复数据:
在这里插入图片描述
2.过滤出存在重复数据的信息:

SQL语句:

SELECT
	dname 
FROM
	dept 
GROUP BY
	dname 
HAVING
	count( dname ) >1

数据库筛选结果:
在这里插入图片描述
3.从重复数据中筛选出一条需要保存的数据:

SQL语句:

SELECT
	min( deptno ) -- max( deptno )
	
FROM
	dept 
GROUP BY
	dname 
HAVING
	count( dname ) >1

这里使用数据库的MIN或者MAX函数筛选出一条需要保存数据即可。

数据库筛选结果:
在这里插入图片描述
4.删除重复数据,即从重复的数据中,删除掉需要保留数据之外的所有信息:

SQL:

DELETE 
FROM
	dept 
WHERE
	dname IN ( SELECT dname FROM dept GROUP BY dname HAVING count( dname ) > 1 ) -- 过滤出重复的dname
	AND deptno NOT IN ( SELECT min( deptno ) AS deptno FROM dept GROUP BY dname HAVING count( dname ) > 1 ) -- 过滤出不在需要保留的id之外的所有id
	

如果是oracle数据库,上面的SQL语句可以正常执行,可是换成mysql数据库,SQL语句执行会报错:

1093 - You can't specify target table 'dept' for update in FROM clause

含义:不能在同一表中查询的数据作为同一表的更新数据。

适用于mysql数据库的SQL:

DELETE 
FROM
	dept 
WHERE
	dname IN ( SELECT * FROM ( SELECT dname FROM dept GROUP BY dname HAVING count( dname ) > 1 ) a ) 
	AND deptno NOT IN ( SELECT * FROM ( SELECT min( deptno ) AS deptno FROM dept GROUP BY dname HAVING count( dname ) > 1 ) b )

数据库最后数据:
在这里插入图片描述
到这里,删除重复数据成功!

删除数据库中的重复记录并保留一条时,关键在于如何识别哪些记录是重复的,并确保只删除多余的那些。以下是几种常见场景及其对应的 SQL 实现方式。 ### 删除基于单个字段的重复记录,保留 `id` 最小的一条 ```sql DELETE FROM lib WHERE name IN ( SELECT name FROM ( SELECT name FROM lib GROUP BY name HAVING COUNT(name) > 1 ) AS a ) AND id NOT IN ( SELECT min_id FROM ( SELECT MIN(id) AS min_id FROM lib GROUP BY name HAVING COUNT(name) > 1 ) AS b ); ``` 该语句通过查找所有 `name` 字段重复的记录,并排除每组中 `id` 最小的那条,从而删除其余的重复项[^1]。 --- ### 删除基于多个字段的重复记录,保留 `id` 最小的一条 当需要根据多个字段(例如 `name` 和 `version`)来判断重复记录时,可以使用如下语句: ```sql DELETE FROM lib WHERE (name, version) IN ( SELECT t.name, t.version FROM ( SELECT name, version FROM lib GROUP BY name, version HAVING COUNT(1) > 1 ) t ) AND id NOT IN ( SELECT dt.minid FROM ( SELECT MIN(id) AS minid FROM lib GROUP BY name, version HAVING COUNT(1) > 1 ) dt ); ``` 此查询利用组合字段 `(name, version)` 来识别重复数据,并仅保留每组中 `id` 最小的记录[^1]。 --- ### 删除重复记录并保留唯一记录的通用方法(适用于 MySQL) 对于不支持子查询中直接引用目标表的情况,可以通过创建临时表的方式来实现相同效果: ```sql CREATE TABLE temp_table AS SELECT * FROM lib WHERE id IN ( SELECT MIN(id) FROM lib GROUP BY name, version ); TRUNCATE TABLE lib; INSERT INTO lib SELECT * FROM temp_table; DROP TABLE temp_table; ``` 此方法首先将要保留数据存入临时表中,清空原表后,再将临时表中的数据重新插入到原表中,从而达到去重的目的。 --- ### 使用窗口函数删除重复记录(适用于支持窗口函数的数据库如 PostgreSQLSQL Server) 如果使用的数据库支持窗口函数,可以更高效地进行操作: ```sql DELETE FROM lib WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY name, version ORDER BY id) AS rn FROM lib ) t WHERE rn > 1 ); ``` 这里使用了 `ROW_NUMBER()` 函数对每组重复数据进行编号,其中 `rn = 1` 表示保留的记录,而 `rn > 1` 的记录将被删除[^2]。 --- ### 注意事项 - 在执行删除操作之前,建议先运行 `SELECT` 查询以确认即将删除数据是否正确。 - 对于大型表,删除操作可能会导致性能问题,最好在低峰期执行。 - 如果数据库支持事务,可以在事务中执行删除操作以便回滚。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder-文小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值