Bootstrap

MySQL 重复数据操作

1、查询重复数据

SELECT a.*
FROM table_a a
INNER JOIN (
    SELECT id_customer
    FROM table_a
    GROUP BY id_customer
    HAVING COUNT(*) > 1
) b ON a.id_customer = b.id_customer;

说明:

  1. 子查询(子选择b)选择所有id_customer并计算每个id_customer的出现次数。
  2. 通过HAVING COUNT(*) > 1条件,子查询仅返回那些出现次数大于1的id_customer
  3. 外部查询通过INNER JOIN操作将table_a表(别名a)与子查询的结果(别名b)连接起来。
  4. 连接条件是a.id_customer = b.id_customer,这意味着只有当id_customer在子查询的结果中(即它重复了)时,对应的行才会被返回。

删除重复数据:
要去除table_a表中id_customer的重复数据,同时保留其中一条记录,可以使用多种方法。这里提供两种常用的方法:

2、删除重复数据

方法一:使用临时表或子查询

如果希望保留每个id_customer的最早(或最新)记录,可以基于一个额外的列(比如创建时间或ID自增列)来决定哪条记录是“最早”或“最新”的。假设有一个名为create_time的列表示记录的创建时间,可以这样做:

-- 假设保留每个id_customer的最新记录
CREATE TEMPORARY TABLE temp_table_a AS
SELECT *
FROM table_a
WHERE (id_customer, create_time) IN (
  SELECT id_customer, MAX(create_time)
  FROM table_a
  GROUP BY id_customer
);


-- 清空原表
TRUNCATE TABLE table_a;


-- 将唯一记录插回原表
INSERT INTO table_a
SELECT * FROM temp_table_a;

或者直接在原表上操作

-- 如果不需要临时表,可以直接使用子查询(但注意性能可能不如临时表)

-- 注意:下面的命令直接在原表上操作,请谨慎使用
DELETE FROM table_a
WHERE (id_customer, create_time) NOT IN (
  SELECT id_customer, MAX(create_time)
  FROM table_a
  GROUP BY id_customer
);

注意:使用DELETE语句时要非常小心,因为它会直接从表中删除数据。确保有一个备份,或者先在测试环境中验证查询。

方法二:使用ROW_NUMBER()窗口函数(MySQL 8.0+)

如果使用的是MySQL 8.0或更高版本,可以利用窗口函数ROW_NUMBER()来为每个id_customer分组内的记录分配一个唯一的序号,然后删除那些序号不是1的记录(假设保留每个分组中的第一条记录)。

-- 假设我们保留每个id_customer的最早记录(基于某个排序准则,这里以created_at为例)
WITH RankedCustomers AS (
  SELECT *,
  ROW_NUMBER() OVER(PARTITION BY id_customer ORDER BY create_time DESC) AS rn
  FROM table_a
)
DELETE FROM table_a
WHERE id IN (
  SELECT id
  FROM RankedCustomers
  WHERE rn > 1
);

在这个例子中,ROW_NUMBER()函数为id_customer的每个分组内的记录分配了一个序号,序号是按照create_time降序排列的。然后,删除了那些序号大于1的记录,即保留了每个id_customer分组中create_time最晚的那条记录。如果想要保留最早的记录,只需将ORDER BY create_time DESC改为ORDER BY create_time ASC
注意:执行删除操作之前,请确保你了解这些操作的影响,并在可能的情况下先在测试环境中验证它们。

;