首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >SQL删除表中重复记录方法总结

SQL删除表中重复记录方法总结

原创
作者头像
织幻妖
发布2025-12-08 17:08:11
发布2025-12-08 17:08:11
1510
举报

在 SQL 中删除表中的重复记录是一个常见的数据清洗操作。由于不同数据库系统(如 MySQL、PostgreSQL、SQL Server、Oracle 等)语法略有差异,下面我会以通用方法为主,并针对常见数据库给出具体示例。


一、通用思路

要删除重复记录,通常需要:

  1. 识别重复行(基于一个或多个字段)
  2. 保留其中一行(通常是最早插入的或具有最小/最大主键的那一行)
  3. 删除其余重复行

二、方法分类与示例

方法1:使用窗口函数(推荐,适用于支持窗口函数的数据库)

示例表结构
代码语言:sql
复制
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    email VARCHAR(100)
);

插入一些重复数据:

代码语言:sql
复制
INSERT INTO employees VALUES
(1, 'Alice', 'alice@example.com'),
(2, 'Bob', 'bob@example.com'),
(3, 'Alice', 'alice@example.com'),  -- 重复
(4, 'Charlie', 'charlie@example.com'),
(5, 'Bob', 'bob@example.com');      -- 重复
删除重复(保留最小 id 的记录)
代码语言:sql
复制
-- PostgreSQL / SQL Server / Oracle / MySQL 8.0+
DELETE FROM employees
WHERE id NOT IN (
    SELECT MIN(id)
    FROM employees
    GROUP BY name, email
);

或者使用窗口函数(更高效):

代码语言:sql
复制
-- 使用 CTE + ROW_NUMBER()
WITH duplicates AS (
    SELECT id,
           ROW_NUMBER() OVER (PARTITION BY name, email ORDER BY id) AS rn
    FROM employees
)
DELETE FROM employees
WHERE id IN (
    SELECT id FROM duplicates WHERE rn > 1
);

注意:MySQL 早期版本(<8.0)不支持在 DELETE 中直接引用自身表的子查询,需用临时表绕过。


方法2:自连接删除(适用于 MySQL < 8.0)

代码语言:sql
复制
-- 删除重复,保留较小 id 的记录
DELETE e1 FROM employees e1
INNER JOIN employees e2
WHERE e1.id > e2.id
  AND e1.name = e2.name
  AND e1.email = e2.email;

此语法仅适用于 MySQL(使用别名进行自连接删除)。


方法3:创建新表(通用但耗资源)

适用于任何数据库,适合一次性清理大量重复数据:

代码语言:sql
复制
-- 1. 创建无重复的新表
CREATE TABLE employees_clean AS
SELECT MIN(id) AS id, name, email
FROM employees
GROUP BY name, email;

-- 2. 删除原表并重命名(或 TRUNCATE + INSERT)
DROP TABLE employees;
ALTER TABLE employees_clean RENAME TO employees;

注意:此方法会丢失原表的索引、约束等,需重新创建。


方法4:使用 EXISTS(通用)

代码语言:sql
复制
DELETE FROM employees e1
WHERE EXISTS (
    SELECT 1
    FROM employees e2
    WHERE e2.name = e1.name
      AND e2.email = e1.email
      AND e2.id < e1.id
);

此写法在 PostgreSQL、SQL Server、Oracle 中有效;MySQL 需加别名或改写。


三、不同数据库注意事项

数据库

是否支持 ROW_NUMBER()

自连接删除语法

子查询限制

MySQL 8.0+

较少

MySQL <8.0

✅(特殊语法)

不能直接删自己

PostgreSQL

支持

SQL Server

支持

Oracle

支持

SQLite

✅(3.25+)

❌(不支持多表 DELETE)

需用临时表

SQLite 示例(只能通过重建表):CREATE TABLE employees_new AS SELECT MIN(id) AS id, name, email FROM employees GROUP BY name, email;DROP TABLE employees; ALTER TABLE employees_new RENAME TO employees;


四、小结:最佳实践建议

  • 有主键/唯一ID:优先用 ROW_NUMBER()MIN(id) 分组保留。
  • 无主键:先加临时 ID 列,再去重。
  • 大数据量:考虑分批删除,避免锁表或事务过大。
  • 生产环境:先备份,再执行删除!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、通用思路
  • 二、方法分类与示例
    • 方法1:使用窗口函数(推荐,适用于支持窗口函数的数据库)
      • 示例表结构
      • 删除重复(保留最小 id 的记录)
    • 方法2:自连接删除(适用于 MySQL < 8.0)
    • 方法3:创建新表(通用但耗资源)
    • 方法4:使用 EXISTS(通用)
  • 三、不同数据库注意事项
  • 四、小结:最佳实践建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档