Carry の Blog Carry の Blog
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carry の Blog

好记性不如烂键盘
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • MySQL

    • MySQL8一键安装配置优化
    • MySQL导出CSV格式解决乱码
    • MySQL 角色管理
    • MySQL网络抓包审计
    • MySQL性能压测
    • MySQL配合Consul读写分离
    • Gh-ost重建表,清除表碎片率
    • MySQL MGR配合MySQL-router实现innodb-cluster
    • MySQL 快速分析binlog定位问题
    • MySQL执行计划分析
    • DBA常用SQL和命令整理备查
    • mysqldump实时同步数据
    • MySQL的事务隔离级别
    • MySQL存储过程批量生成数据
    • MySQL insert on duplicate key update,replace into , insert ignore的理解
    • MySQL不同字符集之间的区别和选择
    • MySQL为什么有时候会选错索引
    • MySQL死锁问题
    • MySQL使用SQL语句查重去重
      • 前言
      • 查找重复数据的基本思路
      • 查找重复数据的SQL模板
      • 实际应用示例
      • 删除重复数据
      • 注意事项
    • MySQLdump逻辑备份
    • MySQL主从跳过异常GITD
    • MySQL8设置slowlog记录所有语句
    • MySQL8快速克隆插件使用指南
    • MySQL8双1设置保障安全
    • MySQL锁
    • innodb cluster安装
    • MySQL里的left join 和right join以及inner join
    • optimize table和 analyze table的区别
    • MySQL 字段的区分度计算公式
    • MySQLReplicaSet 安装
    • 脚本实现MySQL ReplicaSet 高可用
    • MySQL 的Left join,Right join和Inner join 的区别
    • MySQL45讲学习笔记
  • Redis

  • Keydb

  • TiDB

  • MongoDB

  • Elasticsearch

  • Kafka

  • victoriametrics

  • BigData

  • Sqlserver

  • 数据库
  • MySQL
Carry の Blog
2022-03-17
目录

MySQL使用SQL语句查重去重原创

# 前言

在数据库运维过程中,经常会遇到数据重复的问题,比如由于唯一索引调整、程序bug等原因导致的重复数据写入。本文介绍如何使用SQL语句来识别和清理重复数据。

# 查找重复数据的基本思路

查找重复数据的核心思路是:

  1. 确定用于判断重复的字段组合
  2. 使用子查询找出重复记录中除了最新记录之外的其他记录
  3. 可以选择保留最早或最新的记录,通常我们保留最新记录(通过max函数)

# 查找重复数据的SQL模板

点击查看SQL模板
SELECT * FROM
  table_name AS ta
WHERE
  ta.id <> (
    SELECT
      max(tb.id)
    FROM
      table_name AS tb
    WHERE
      ta.duplicate_column = tb.duplicate_column  -- 用于判断重复的字段
  );
1
2
3
4
5
6
7
8
9
10
11

这个模板中:

  • table_name 是要操作的表名
  • id 是表的主键
  • duplicate_column 是用于判断重复的字段,可以是单个字段,也可以是多个字段的组合

# 实际应用示例

下面是一个更复杂的实际应用示例,展示了如何在特定时间范围内查找多字段组合重复的数据:

点击查看SQL实例
SELECT * FROM
  my_test_table_name
WHERE
  id IN (
    SELECT id
    FROM (
      SELECT *
      FROM my_test_table_name
      WHERE updated_at BETWEEN '2022-03-15 18:20:00' AND '2022-03-15 19:30:00'
    ) AS ta
    WHERE ta.id <> (
      SELECT max(tb.id)
      FROM (
        SELECT *
        FROM my_test_table_name
        WHERE updated_at BETWEEN '2022-03-15 18:20:00' AND '2022-03-15 19:30:00'
      ) AS tb
      WHERE
        ta.tran_start_time = tb.tran_start_time
        AND ta.tran_end_time = tb.tran_end_time
        AND ta.member_account = tb.member_account
    )
  );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

这个示例展示了:

  • 如何在指定时间范围内查找重复数据
  • 如何基于多个字段组合(tran_start_time、tran_end_time、member_account)判断重复
  • 如何使用子查询优化查询性能

# 删除重复数据

确认查询结果无误后,可以将 SELECT 语句改写为 DELETE 语句来删除重复数据:

点击查看删除语句
DELETE FROM
  my_test_table_name
WHERE
  id IN (
    SELECT id
    FROM (
      SELECT *
      FROM my_test_table_name
      WHERE updated_at BETWEEN '2022-03-15 18:20:00' AND '2022-03-15 19:30:00'
    ) AS ta
    WHERE ta.id <> (
      SELECT max(tb.id)
      FROM (
        SELECT *
        FROM my_test_table_name
        WHERE updated_at BETWEEN '2022-03-15 18:20:00' AND '2022-03-15 19:30:00'
      ) AS tb
      WHERE
        ta.tran_start_time = tb.tran_start_time
        AND ta.tran_end_time = tb.tran_end_time
        AND ta.member_account = tb.member_account
    )
  );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 注意事项

  1. 执行删除操作前,强烈建议先使用 SELECT 语句验证查询结果
  2. 建议在删除前做好数据备份
  3. 如果数据量较大,建议分批处理,避免长时间锁表
  4. 删除后检查唯一索引约束,确保不会再次产生重复数据
#重复数据处理#SQL#数据清理
上次更新: 4/24/2025

← MySQL死锁问题 MySQLdump逻辑备份→

最近更新
01
tidb fast ddl
04-04
02
TiDB配置文件调优 原创
04-03
03
如何移除TiDB中的表分区 原创
04-03
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式