数据库中单表根据某几个字段去重【我】

java类:

package duplicate.removal;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DuplicateRemoval {
    private final static Logger logger = LoggerFactory.getLogger(DuplicateRemoval.class);

    public static void main(String[] args) {
        //查询重复数据
        List<Map> repeatedDataInfo = this.selectList("xxxx.getRepeatedDataInfo");
        logger.info("查询是否存在重复数据,查询结果:{}",repeatedDataInfo);
        if(repeatedDataInfo!=null && repeatedDataInfo.size()>0) {
            //根据查询到的重复数据条件组 循环删除重复记录
            for (Map map : repeatedDataInfo) {
                //删除重复记录只保留一个
                logger.info("查询客户关系存在重复数据,执行循环删除,当前删除条件:{}",map);
                //先查询一下重复数据,打印到日志里以备后查,这一步可以没有
                List<Map> dataList = this.selectList("xxxx.getRepeatedDataList",map);
                logger.info("查询客户关系存在重复数据,执行循环删除,当前即将删除数据集合:{}",dataList);
                //真的执行删除(这里是逻辑删除,只改状态字段)操作
                this.update("xxxx.updateRepeatedData", map);
            }
        }
    }

}

Mapper文件:

<!-- 获取重复记录字段信息列表
        去重条件:表中的 P_ID、CUST_ID、REGION_CODE 三个字段一样的数据多余2条即认为是重复数据,
        where后面可以增加一些其他附件查询条件,
        返回结果: MAX(ID) ID 是取出每一组重复条件数据中重复数据ID最大的一个,作为后面的保留数据
                其他三项为重复数据的三个字段值
 -->    
    <select id="getRepeatedDataInfo" resultType="java.util.Map">
         SELECT
            MAX(ID) ID,
            u.P_ID P_ID,
            u.CUST_ID CUST_ID,
            u.region_code REGION_CODE,
            COUNT(1) cnt
        FROM
            CUST_RECORD u
        WHERE
            status_cd = '1000'
            AND SERIAL_NUM LIKE 'PL%'
        GROUP BY
            u.P_ID,
            u.CUST_ID,
            u.region_code
        HAVING
            cnt > 1
        LIMIT 99999;
       </select>
       
       <!-- 获取将要删除的重复记录详情集合 
           根据第一步查询出的重复数据的条件组,查询每一组重复数据,其中ID != #{ID}过滤掉要保留的那条数据
       -->
       <select id="getRepeatedDataList" parameterType="java.util.Map" resultType="java.util.Map">
           SELECT
            *
        FROM
            CUST_RECORD
        WHERE
            status_cd = '1000'
        AND    P_ID = #{P_ID}
        AND CUST_ID = #{CUST_ID}
        AND region_code = #{REGION_CODE}
        AND ID != #{ID}
        AND SERIAL_NUM LIKE 'PL%';
       </select>
       
    <!-- 删除(更新状态为失效)重复记录只保留一个 
        根据第一步查询出的重复数据的条件组,删除每一组重复数据,其中ID != #{ID}过滤掉要保留的那条数据
    -->
    <update id="updateRepeatedData" parameterType="java.util.Map">
        update
            CUST_RECORD
        set STATUS_CD = '1100',STATUS_DATE = NOW(),UPDATE_DATE=NOW()
        WHERE
            status_cd = '1000'
        AND    P_ID = #{P_ID}
        AND CUST_ID = #{CUST_ID}
        AND region_code = #{REGION_CODE}
        AND ID != #{ID}
        AND SERIAL_NUM LIKE 'PL%';
    </update>
    
    
  

注意:

此方法有一个问题就是如果当前表中数据量比较大时,第一个分组查询可能会报数据库内存溢出,或者查询速度特别慢,所以如果要分组的数据量很大这种方式尽量不要用。

最好的去重方式就是在插入前先查询判断,如果数据库中不存在才插入。

原文地址:https://www.cnblogs.com/libin6505/p/11389359.html