欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL處理重復(fù)數(shù)據(jù)完整代碼實(shí)例

 更新時(shí)間:2025年09月24日 09:16:05   作者:kushu7  
在數(shù)據(jù)庫管理中,查找重復(fù)值是一項(xiàng)常見需求,下面這篇文章主要介紹了MySQL處理重復(fù)數(shù)據(jù)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在數(shù)據(jù)庫管理中,重復(fù)數(shù)據(jù)是最常見的 “隱形殺手” 之一。它不僅會(huì)浪費(fèi)存儲(chǔ)空間、拖慢查詢速度,還可能導(dǎo)致業(yè)務(wù)邏輯混亂(如統(tǒng)計(jì)結(jié)果失真、訂單重復(fù)處理)。

一、認(rèn)識(shí)重復(fù)數(shù)據(jù):從 “什么是重復(fù)” 開始

重復(fù)數(shù)據(jù)并非僅指完全相同的記錄,在實(shí)際業(yè)務(wù)中可分為兩類:

  • 完全重復(fù):所有字段值均相同的記錄(如誤操作導(dǎo)致的重復(fù)插入)。
  • 部分重復(fù):核心字段相同但非關(guān)鍵字段不同的記錄(如同一用戶的重復(fù)注冊(cè),僅注冊(cè)時(shí)間不同)。

二、檢測(cè)重復(fù)數(shù)據(jù):

1. 檢測(cè)完全重復(fù)記錄

-- 查找完全重復(fù)的記錄
SELECT * FROM table_name
WHERE (col1, col2, ..., coln) IN (
SELECT col1, col2, ..., coln
FROM table_name
GROUP BY col1, col2, ..., coln
HAVING COUNT(*) > 1
);

適用于所有字段均需唯一的場景(如配置表、字典表):

示例:檢測(cè)user_config表中完全重復(fù)的配置記錄:

SELECT * FROM user_config
WHERE (user_id, config_key, config_value) IN (
SELECT user_id, config_key, config_value
FROM user_config
GROUP BY user_id, config_key, config_value
HAVING COUNT(*) > 1
);

2. 檢測(cè)部分重復(fù)記錄(按核心字段)

適用于僅需保證核心字段唯一的場景(如用戶表的手機(jī)號(hào)、訂單表的訂單號(hào)):

-- 按核心字段分組,查找重復(fù)記錄
SELECT core_col1, core_col2, COUNT(*) AS duplicate_count
FROM table_name
GROUP BY core_col1, core_col2
HAVING COUNT(*) > 1;

示例:檢測(cè)users表中重復(fù)的手機(jī)號(hào)(核心字段為phone):

-- 查看重復(fù)手機(jī)號(hào)及重復(fù)次數(shù)
SELECT phone, COUNT(*) AS duplicate_count
FROM users
GROUP BY phone
HAVING COUNT(*) > 1;
-- 查看重復(fù)手機(jī)號(hào)對(duì)應(yīng)的完整記錄
SELECT * FROM users
WHERE phone IN (
SELECT phone
FROM users
GROUP BY phone
HAVING COUNT(*) > 1
)
ORDER BY phone;

3. 高級(jí)檢測(cè):帶條件的重復(fù)記錄

結(jié)合業(yè)務(wù)邏輯篩選重復(fù)記錄(如重復(fù)且狀態(tài)有效的訂單):

-- 查找狀態(tài)為"已支付"的重復(fù)訂單
SELECT order_no, COUNT(*) AS duplicate_count
FROM orders
WHERE status = 'PAID'
GROUP BY order_no
HAVING COUNT(*) > 1;

4. 使用窗口函數(shù)標(biāo)記重復(fù)記錄(MySQL 8.0+)

通過ROW_NUMBER()為重復(fù)記錄編號(hào),便于后續(xù)處理:

-- 為重復(fù)手機(jī)號(hào)的記錄編號(hào)(按注冊(cè)時(shí)間排序)
SELECT
id, phone, register_time,
ROW_NUMBER() OVER (PARTITION BY phone ORDER BY register_time) AS rn
FROM users;
  • 結(jié)果中rn > 1的記錄即為需要處理的重復(fù)數(shù)據(jù)。

三、刪除重復(fù)數(shù)據(jù):保留有效記錄

刪除重復(fù)數(shù)據(jù)的核心原則是:保留一條有效記錄(如最新 / 最早的記錄),刪除其余重復(fù)項(xiàng)。以下是 4 種實(shí)用方法:

1. 帶唯一標(biāo)識(shí)的重復(fù)記錄刪除(推薦)

若表中有自增主鍵(如id),可通過子查詢定位并刪除重復(fù)記錄:

-- 保留重復(fù)手機(jī)號(hào)中id最小的記錄(即最早插入的記錄)
DELETE FROM users
WHERE id NOT IN (
SELECT min_id FROM (
-- 子查詢嵌套避免"不能從同表查詢并刪除"的限制
SELECT MIN(id) AS min_id
FROM users
GROUP BY phone
HAVING COUNT(*) > 1
) AS temp
);

邏輯解析

  1. 內(nèi)層子查詢找出每組重復(fù)記錄中的最小id(要保留的記錄)。
  1. 外層刪除所有id不在保留列表中的記錄。

2. 無唯一標(biāo)識(shí)的重復(fù)記錄刪除

若表無主鍵,可通過所有字段組合定位重復(fù)記錄:

-- 保留完全重復(fù)記錄中一條(需指定所有字段)
DELETE t1 FROM table_name t1
JOIN table_name t2
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2
AND ...
AND t1.coln = t2.coln
WHERE t1.ctid < t2.ctid; -- 利用隱藏列ctid區(qū)分物理位置(僅InnoDB有效)

3. 按條件保留記錄(如最新記錄)

通過排序保留指定條件的記錄(如最新注冊(cè)的用戶):

-- 保留重復(fù)手機(jī)號(hào)中注冊(cè)時(shí)間最新的記錄
DELETE t1 FROM users t1
JOIN users t2
ON t1.phone = t2.phone
AND t1.register_time < t2.register_time; -- t1為舊記錄

4. 批量刪除大表重復(fù)數(shù)據(jù)(性能優(yōu)化)

當(dāng)表數(shù)據(jù)量超過 100 萬行時(shí),直接刪除可能導(dǎo)致鎖表,建議分批次處理:

-- 每次刪除1000條重復(fù)記錄(循環(huán)執(zhí)行至無重復(fù))
DELETE FROM users
WHERE id IN (
SELECT id FROM (
SELECT id
FROM (
SELECT
id,
ROW_NUMBER() OVER (PARTITION BY phone ORDER BY register_time) AS rn
FROM users
) AS t
WHERE rn > 1
LIMIT 1000 -- 限制單次刪除數(shù)量
) AS temp
);

注意事項(xiàng):

  • 刪除前必須備份:執(zhí)行CREATE TABLE users_backup AS SELECT * FROM users;創(chuàng)建備份表。
  • 使用事務(wù):通過BEGIN; DELETE ...; COMMIT;確保刪除可回滾。
  • 刪除后優(yōu)化:執(zhí)行OPTIMIZE TABLE users;回收碎片空間。

四、預(yù)防重復(fù)數(shù)據(jù):從源頭阻斷

處理重復(fù)數(shù)據(jù)的最佳方式是提前預(yù)防,以下是 3 種核心手段:

1. 建立唯一約束(最有效)

通過唯一索引主鍵強(qiáng)制核心字段唯一:

-- 為手機(jī)號(hào)添加唯一索引,阻止重復(fù)插入
CREATE UNIQUE INDEX uk_users_phone ON users(phone);
-- 復(fù)合唯一索引(如同一用戶的配置鍵唯一)
CREATE UNIQUE INDEX uk_user_config ON user_config(user_id, config_key);
  • 插入重復(fù)數(shù)據(jù)時(shí),MySQL 會(huì)直接報(bào)錯(cuò)(Duplicate entry),避免污染數(shù)據(jù)。

2. 插入時(shí)處理重復(fù)數(shù)據(jù)

通過INSERT ... IGNORE或REPLACE INTO在插入階段處理重復(fù):

-- 插入時(shí)忽略重復(fù)記錄(不報(bào)錯(cuò),返回警告)
INSERT IGNORE INTO users (phone, name)
VALUES ('13800138000', '張三');
-- 重復(fù)時(shí)替換舊記錄(刪除舊記錄后插入新記錄)
REPLACE INTO users (phone, name)
VALUES ('13800138000', '張三');
  • 適用場景:數(shù)據(jù)同步、批量導(dǎo)入等可能產(chǎn)生重復(fù)的場景。

3. 業(yè)務(wù)層控制

在應(yīng)用程序中添加重復(fù)校驗(yàn)邏輯:

// Java示例:插入前檢查手機(jī)號(hào)是否已存在
public boolean addUser(User user) {
// 先查詢是否存在重復(fù)手機(jī)號(hào)
if (userDao.existsByPhone(user.getPhone())) {
throw new DuplicateException("手機(jī)號(hào)已注冊(cè)");
}
return userDao.insert(user) > 0;
}
  • 配合數(shù)據(jù)庫唯一索引,形成 “雙重保障”。

總結(jié)

到此這篇關(guān)于MySQL處理重復(fù)數(shù)據(jù)的文章就介紹到這了,更多相關(guān)MySQL處理重復(fù)數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL分區(qū)之RANGE分區(qū)詳解

    MySQL分區(qū)之RANGE分區(qū)詳解

    Range分區(qū)是最常用的一種分區(qū)類型,它是根據(jù)某個(gè)列的值劃分為幾個(gè)連續(xù)的區(qū),行數(shù)據(jù)根據(jù)該列的值分別放入到不同的分區(qū),這篇文章主要給大家介紹了關(guān)于MySQL分區(qū)之RANGE分區(qū)的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • 安裝rpm包時(shí)提示錯(cuò)誤:依賴檢測(cè)失敗的解決方法

    安裝rpm包時(shí)提示錯(cuò)誤:依賴檢測(cè)失敗的解決方法

    今天在虛擬機(jī)中裝MySQL的時(shí)候,突然出現(xiàn)了這個(gè)依賴檢測(cè)錯(cuò)誤,下面這篇文章主要給大家介紹了關(guān)于安裝rpm包時(shí)提示錯(cuò)誤:依賴檢測(cè)失敗的解決方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • 用HAProxy來檢測(cè)MySQL復(fù)制的延遲的教程

    用HAProxy來檢測(cè)MySQL復(fù)制的延遲的教程

    這篇文章主要介紹了用HAProxy來檢測(cè)MySQL復(fù)制的延遲的教程,HAProxy需要使用到PHP腳本,需要的朋友可以參考下
    2015-04-04
  • 一篇文章帶你了解MySQL數(shù)據(jù)庫約束

    一篇文章帶你了解MySQL數(shù)據(jù)庫約束

    數(shù)據(jù)庫中要管理很多數(shù)據(jù),但是這些數(shù)據(jù)是否正確、是否非法,光靠人力來檢驗(yàn)是遠(yuǎn)遠(yuǎn)不夠的,因此我們想讓數(shù)據(jù)庫擁有豐富的檢驗(yàn)和校驗(yàn)?zāi)芰?所以便引入了約束,下面這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫約束的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • MySQL5.6基本優(yōu)化配置

    MySQL5.6基本優(yōu)化配置

    這篇文章主要介紹了MySQL5.6基本優(yōu)化配置,詳細(xì)分解了MySQL5.6需要優(yōu)化的配置項(xiàng),最終給出了一個(gè)優(yōu)化案例,需要的朋友可以參考下
    2014-06-06
  • 一次MySQL慢查詢導(dǎo)致的故障

    一次MySQL慢查詢導(dǎo)致的故障

    這篇文章主要介紹了如何對(duì)MySQL慢查詢導(dǎo)致的故障進(jìn)行處理,慢查詢是我們?cè)趍ysql中經(jīng)常需要使用到的一個(gè)很方便的功能,慢查詢對(duì)于跟蹤有問題的查詢很有用,需要的朋友可以參考下
    2015-08-08
  • mysql整數(shù)數(shù)據(jù)類型深入解析

    mysql整數(shù)數(shù)據(jù)類型深入解析

    本篇文章是對(duì)mysql中的整數(shù)數(shù)據(jù)類型進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • MYSQL中EXISTS的用法小結(jié)

    MYSQL中EXISTS的用法小結(jié)

    在MySQL數(shù)據(jù)庫中,EXISTS是一種強(qiáng)大的工具,用于處理復(fù)雜的查詢需求,本文主要介紹了MYSQL中EXISTS的用法小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • SQL Server服務(wù)器監(jiān)控

    SQL Server服務(wù)器監(jiān)控

    這篇文章主要介紹了SQL Server服務(wù)器監(jiān)控,SQL server監(jiān)控是收集、聚合和監(jiān)控SQL服務(wù)器的各種指標(biāo)的過程,更多相關(guān)內(nèi)容需要的朋友可以參考一下
    2022-09-09
  • 史上最簡單的MySQL數(shù)據(jù)備份與還原教程(下)(三十七)

    史上最簡單的MySQL數(shù)據(jù)備份與還原教程(下)(三十七)

    這篇文章主要為大家詳細(xì)介紹了史上最簡單的MySQL數(shù)據(jù)備份與還原教程下篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評(píng)論