学习的过程中总是能遇到各种各样的问题
清理手机号重复的数据,但要求,每个手机号 留存 3条
思路
  • 首先手机号分组查询,每次查询 100 组(也就是把手机号相同的数据 归纳到一起,并按照重复数量降序,取前 100个不相同手机号)
  • 根据手机号获取对应手机号的所有 id
  • 保留前三个 id,删除多余的数据
思路有了动手吧!

config.ini 通用的配置信息,按个人习惯使用

[config]
auth = Eitaqx@163.com
version = 1.0.0
desc = config.ini # 仅用来保存配置信息

[sql_link] # 数据库连接信息
host = mysql.rds.yun.com
database = mysql
user = root
password = 123456
port = 3306

config.py配置模块,只是为了 获取 .ini 中配置信息

import configparser
config = configparser.ConfigParser()
config.read('./config/config.ini', encoding='utf-8')


class Config:
   """
   用来设置/获取配置信息
   """
   global config

   @staticmethod
   def get(name='config'):
      """
      :params name
      :return dictionary
      获取指定的配置信息
      """
      dictionary = {}
      for v in config.items(name):
         dictionary[v[0]] = v[1]
      return dictionary
	....

删除程序,注意:sql执行失败回滚,异常处理,连接超时等 没有做处理

# -*- coding: utf-8 -*-
import pymysql
from config.index import Config
config = Config()


class RemoveRepeatMobile:
    global config

    def __init__(self):
        self.connect()
        self.limit = 100
        self.run()

    def connect(self):
        """
            连接数据库
        """
        sql_link = {
            **config.get('sql_link'),
            "cursorclass": pymysql.cursors.DictCursor,
            'port': int(config.get('sql_link')['port'])
        }
        self.db = pymysql.connect(**sql_link)
        self.cursor = self.db.cursor()
        print(':::数据库连接成功!')

    def run(self):
        """
            处理重复手机号流程
        """
        mobile_list = self.checked_mobile()
        for v in mobile_list:
            if v['count'] > 3:
                id = self.select_mobile_id(v['mobile'])
                self.remove_repeat_info(id, v['mobile'])
            else:
                print(f":::{v['mobile']}:{v['count']}条")
        self.run()

    def checked_mobile(self):
        """
            :return list
            分组查询重复手机号,并统计相应手机号重复次数
        """
        print(':::正在查询数据...')
        self.cursor.execute(f"SELECT mobile, id, COUNT(*) as count from infolist GROUP BY mobile ORDER BY count DESC LIMIT {self.limit}")
        group = self.cursor.fetchall()
        print(':::查询数据成功...')
        if group[0]['count'] <= 3:
            print(":::删除数据结束")
            exit()
        return group

    def select_mobile_id(self, mobile):
        """
            :params mobile
            :reurn list
            获取重复手机id(前3条信息除外),并返回id列表
        """
        print(':::获取重复手机id(前3条信息除外)')
        # SELECT id from infolist WHERE mobile={mobile} ORDER BY id ASC
        # 这样就可以取到 同一手机号 下的所有 id 了然后在针对每个 id 进行删除
        # 然而跑起来,却是 半天才能处理一个 手机号,突然
        # 程序刚跑起来,又想到,为什么要获取同一手机号所有的 id 呢,我只要按顺序采集 获取 3条 不就满足条件了吗
        # 我只需要按照 手机号 和 id 大于 第 三条 不就可以满足条件了吗,当然第3条也是可以的
        # SELECT id from infolist WHERE mobile={mobile} ORDER BY id ASC LIMIT 2,1
        self.cursor.execute(f"SELECT id from infolist WHERE mobile={mobile} ORDER BY id ASC LIMIT 3")
        mobile_list = self.cursor.fetchall()
        print(f'需要删除数量:{len(mobile_list)-3}')
        return mobile_list[2]['id']

    def remove_repeat_info(self, id, mobile):
        print(id, mobile)
        print(f":::正在删除手机号:{mobile}")
        # 刚开始使用
        # for v in ids:
        #	self.cursor.execute(f"DELETE FROM infolist WHERE id={v}")
        # self.db.commit()
        # 结果,,,等了很久才处理了一个 2.6万条重复 手机号 的数据,
        # 之后想到,如果手机号确定,按照 id 进行排序
        # 这样 我只要删除 小于 第三个 id 的这样是不是就很快了
        # 修改了程序之后果然很快了
        self.cursor.execute(f"DELETE FROM infolist WHERE mobile={mobile} AND id>{id}")
        self.db.commit()
        print(":::删除一组成功")


if __name__ == "__main__":
    RemoveRepeatMobile()