• mysql 删除表中重复数据并保留一条


    最近有个需求,给角色添加菜单权限,这是一个role_menu 表。里面存放的是角色id和菜单id,是批量给一种类型角色添加,但有可能角色人为添加过,因为数据量还是比较大的,如果先查询这个有没有添加过再添加会很耗时,而统一不管有没有添加过一并添加则很快,这就需要后续给重复数据给删除掉,于是有了今天的分享。 我这里只做一个列子,工作代码安全底线大家谨记哈。
    准备一张表 用的是mysql8 大家自行更改

    /*
     Navicat Premium Data Transfer
    
     Source Server         : localmysql
     Source Server Type    : MySQL
     Source Server Version : 80030
     Source Host           : localhost:3306
     Source Schema         : nie_db
    
     Target Server Type    : MySQL
     Target Server Version : 80030
     File Encoding         : 65001
    
     Date: 17/08/2022 10:49:41
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for message
    -- ----------------------------
    DROP TABLE IF EXISTS `message`;
    CREATE TABLE `message`  (
      `id` bigint(0) NOT NULL,
      `message_title` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
      `message_context` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
      `send_peo` bigint(0) NULL DEFAULT NULL,
      `receive_peo` bigint(0) NULL DEFAULT NULL,
      `scope` int(0) NULL DEFAULT 0,
      `del_flag` tinyint(0) NULL DEFAULT 0,
      `create_time` datetime(0) NULL DEFAULT NULL,
      `creator` tinyint(0) NULL DEFAULT NULL,
      `update_time` datetime(0) NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of message
    -- ----------------------------
    INSERT INTO `message` VALUES (1, '测试消息', '消息内容', 23, 1231, 0, 0, '2022-08-17 10:39:51', 3, '2022-08-17 10:40:00');
    INSERT INTO `message` VALUES (2, '测试消息', '消息内容', 23, 1231, 0, 0, '2022-08-17 10:39:51', 3, '2022-08-17 10:40:00');
    INSERT INTO `message` VALUES (3, '测试消息', '消息内容', 23, 1231, 0, 0, '2022-08-17 10:39:51', 3, '2022-08-17 10:40:00');
    INSERT INTO `message` VALUES (4, '测试消息', '消息内容', 23, 1231, 0, 0, '2022-08-17 10:39:51', 3, '2022-08-17 10:40:00');
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    创建表并添加四条相同的数据
    接下来是我们这次的重头,我封装了一个存储过程,具体的逻辑都在注释里了,你也可以分析然后单独拿出来分批次执行sql

    在这里插入图片描述

    CREATE DEFINER=`root`@`localhost` PROCEDURE `remove`()
    BEGIN
    DECLARE count_all INT DEFAULT 0;
    DECLARE count_copy INT DEFAULT 1;
    
    -- 创建一个临时复制表,并将目标表数据复制进来
    DROP TABLE if exists message_01 ;
    create TEMPORARY TABLE message_01 (SELECT * FROM message);
    
    -- 查询去重后实际条数 并赋值给我们的变量 去重根据实际需求更改GROUP BY 后面条件
    SELECT COUNT(1) into count_all from (select COUNT(1) FROM message WHERE del_flag = 0 GROUP BY message_title,message_context) t ;
    
    /*删除复制表的重复数据并保留一条  保留哪条数据可以自己根据条件调节,
    比如最小id等等,就是条件问题 还有就是去重根据实际需求更改GROUP BY 后面条件
    这里如果使用了逻辑删除,有需要保留数据的可以改成修改逻辑删除字段
    */
    DELETE FROM message_01 WHERE ID NOT IN (
    select t.id FROM (select MAX(id) as id FROM message WHERE del_flag = 0 GROUP BY message_title,message_context) t
    );
    
    -- 再次不去重查询 如结果和查询结果一样则操作正确且完整
    select COUNT(1) INTO count_copy FROM message_01 WHERE del_flag = 0 ;
    
    -- 进行最后两次查询结果比对
    IF count_all = count_copy THEN
    TRUNCATE message;
    INSERT INTO message (SELECT * FROM message_01);
    SELECT 'success';
    ELSE 
    SELECT '改造失败',count_all AS '原表条数',count_copy AS '复制表删除重复数据后统计的条数';
    END IF;
    
    END
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    另外创建存储过程,就是再函数那里右键 -》过程-》输入名字-》完成 ,你也可以百度下怎么创建的,我这里就不说太多啦,如果有用,点个赞肯定一下吧,谢谢您啦。

  • 相关阅读:
    【C++基础】10. 指针
    使用 Argon2 的 Java 密码散列
    如何设计一个 JVM 语言下的 LLM 应用开发框架?以 Chocolate Factory 为例
    Java 效率工具, 大幅度提高开发效率
    drf——分页、jwt介绍与原理、jwt快速使用、jwt源码分析、jwt自定义返回格式、自定义用户签发token、自定义token认证类
    Java自学路线图之Java进阶自学
    LeetCode刷题day24||回溯算法理论基础&&77. 组合--回溯
    【Proteus仿真】【Arduino单片机】PWM电机调速
    R语言ggplot2可视化:使用ggplot2可视化散点图、在geom_point参数中设置show_legend参数为FALSE配置不显示图例信息
    点集合的三角剖分
  • 原文地址:https://blog.csdn.net/Prf_Nie/article/details/126381052