0
点赞
收藏
分享

微信扫一扫

巧用 CTE 公共表达式删除 MySQL 重复数据

一段时间后,大多数应用程序可能由于bug而出现重复行,这不仅影响用户体验,还增加了存储需求并降低数据库性能。可以通过一个 SQL 查询来完成整个清理过程,从而有效解决这一问题。


使用范例

-- 创建表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);

-- 插入数据,包括重复数据
INSERT INTO users (name, email) VALUES 
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
('Alice', 'alice@example.com'),  -- 重复数据
('Charlie', 'charlie@example.com'),
('Bob', 'bob@example.com');      -- 重复数据

巧用 CTE 公共表达式删除 MySQL 重复数据

WITH duplicates AS (
  SELECT id, ROW_NUMBER() OVER(
    PARTITION BY name, email
    ORDER BY id DESC
  ) AS rownum
  FROM users
)
DELETE users 
FROM users 
JOIN duplicates USING(id) 
WHERE duplicates.rownum > 1;

输出结果:

mysql> select * from users;
+----+---------+---------------------+
| id | name    | email               |
+----+---------+---------------------+
|  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     |
+----+---------+---------------------+
5 rows in set (0.00 sec)

mysql> WITH duplicates AS (
    ->   SELECT id, ROW_NUMBER() OVER(
    ->     PARTITION BY name, email
    ->     ORDER BY id DESC
    ->   ) AS rownum
    ->   FROM users
    -> )
    -> DELETE users 
    -> FROM users 
    -> JOIN duplicates USING(id) 
    -> WHERE duplicates.rownum > 1;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from users;
+----+---------+---------------------+
| id | name    | email               |
+----+---------+---------------------+
|  3 | Alice   | alice@example.com   |
|  4 | Charlie | charlie@example.com |
|  5 | Bob     | bob@example.com     |
+----+---------+---------------------+
3 rows in set (0.00 sec)

解读:

这个SQL语句可以分为两个主要部分

1)WITH子句(公共表表达式,CTE):

这部分创建了一个名为duplicates的临时结果集。它对users表进行操作:

  • 使用PARTITION BY name, email对名字和邮箱相同的记录进行分组。
  • 在每个分组内,使用ORDER BY id DESC按id降序排序。
  • 为每条记录分配一个rownum,这个数字在每个分组内从1开始计数。


2)DELETE语句:

这部分执行实际的删除操作:

  • 它将users表与我们刚刚创建的duplicates结果集进行JOIN。
  • 删除条件是WHERE duplicates.rownum > 1,意味着它会删除每组重复记录中除了第一条(rownum = 1)之外的所有记录。

需要注意的是,这个DELETE语句的语法可能不被所有数据库系统支持。例如,在MySQL中这是有效的语法,但在其他一些数据库系统中可能需要稍作调整。

总的来说,这个查询的目的是:

  1. 找出users表中名字和邮箱相同的记录。
  2. 对于每组重复记录,保留id最大的那一条(因为是按id降序排序)。
  3. 删除其他所有重复记录。

这种方法可以有效地清理数据库中的重复用户记录,同时保留每组重复记录中最新的(假设id越大越新)一条记录。


举报

相关推荐

0 条评论