SQL中删除重复数据保留一条的高效方法
SQL中删除重复数据保留一条的高效方法在数据库管理中,处理重复数据是常见的需求。我们这篇文章将详细介绍在SQL中删除重复数据并保留一条记录的多种方法,包括使用ROW_NUMBER()窗口函数、GROUP BY与MINMAX结合、临时表法以
SQL中删除重复数据保留一条的高效方法
在数据库管理中,处理重复数据是常见的需求。我们这篇文章将详细介绍在SQL中删除重复数据并保留一条记录的多种方法,包括使用ROW_NUMBER()窗口函数、GROUP BY与MIN/MAX结合、临时表法以及DISTINCT关键字等。我们这篇文章内容包括但不限于:ROW_NUMBER()窗口函数法;GROUP BY保留极值法;临时表替换法;DISTINCT创建新表法;注意事项;6. 常见问题解答。
一、ROW_NUMBER()窗口函数法(推荐)
这是最灵活且高效的方法,适用于大多数现代SQL数据库:
-- 以MySQL为例
DELETE FROM your_table
WHERE id NOT IN (
SELECT id FROM (
SELECT
id,
ROW_NUMBER() OVER (PARTITION BY column1, column2 ORDER BY id) AS row_num
FROM your_table
) t
WHERE t.row_num = 1
);
原理说明:窗口函数按指定列分组(PARTITION BY)并为每组数据生成序号,总的来看只保留每组的第一条记录(row_num=1)。优点是可以精确控制保留哪条记录(通过ORDER BY子句)。
二、GROUP BY保留极值法
适用于有唯一标识列(如自增ID)的情况:
-- 保留ID最小的记录
DELETE FROM your_table
WHERE id NOT IN (
SELECT MIN(id)
FROM your_table
GROUP BY column1, column2 -- 重复判定列
);
这种方法通过GROUP BY找出每组的最小ID,然后删除不在这个集合中的记录。注意:如果不想保留ID最小的记录,可将MIN改为MAX。
三、临时表替换法
适合数据量较大且需要保留最新插入记录的场景:
-- 1. 创建临时表存储不重复数据
CREATE TABLE temp_table AS
SELECT * FROM your_table
WHERE 1=0;
-- 2. 插入去重数据(保留每组总的来看插入的记录)
INSERT INTO temp_table
SELECT * FROM your_table t1
WHERE t1.id = (
SELECT MAX(t2.id)
FROM your_table t2
WHERE t1.column1 = t2.column1
AND t1.column2 = t2.column2
);
-- 3. 替换原表
DROP TABLE your_table;
RENAME TABLE temp_table TO your_table;
四、DISTINCT创建新表法
最简洁的方法,但会丢失未包含在DISTINCT中的列:
-- 创建新表并插入去重数据
CREATE TABLE new_table AS
SELECT DISTINCT column1, column2, column3 -- 指定需要去重的列
FROM your_table;
-- 替换原表
DROP TABLE your_table;
RENAME TABLE new_table TO your_table;
五、重要注意事项
1. 执行前务必备份数据,防止误操作
2. 大表操作建议在非高峰期进行
3. 事务处理:MySQL等数据库可在执行前加BEGIN TRANSACTION,确认无误后再COMMIT
4. 复合唯一键:应根据实际业务需求选择正确的去重列组合
5. 性能考虑:对于超大型表,临时表法通常比直接DELETE更高效
六、常见问题解答
如何删除完全相同的重复记录?
使用以下语句可以删除所有列值完全相同的记录:
DELETE t1 FROM table t1 JOIN table t2
WHERE t1.id < t2.id AND t1.col1 = t2.col1 AND ... [所有列相等条件]
Oracle数据库如何处理?
Oracle可以使用ROWID:
DELETE FROM your_table
WHERE ROWID NOT IN (
SELECT MIN(ROWID)
FROM your_table
GROUP BY column1, column2
);
如何保留最新的记录而不是ID最小的?
在ROW_NUMBER()或GROUP BY方法中,将ORDER BY/MIN改为按时间字段降序即可:
ROW_NUMBER() OVER (PARTITION BY... ORDER BY create_time DESC)
相关文章