MySQL 大批量插入,如何過濾掉重復(fù)數(shù)據(jù)?
加班原因是上線,解決線上數(shù)據(jù)庫存在重復(fù)數(shù)據(jù)的問題,發(fā)現(xiàn)了程序的bug,很好解決,有點(diǎn)問題的是,修正線上的重復(fù)數(shù)據(jù)。
線上庫有6個(gè)表存在重復(fù)數(shù)據(jù),其中2個(gè)表比較大,一個(gè)96萬+、一個(gè)30萬+,因?yàn)橹疤幚磉^相同的問題,就直接拿來了上次的Python去重腳本,腳本很簡(jiǎn)單,就是連接數(shù)據(jù)庫,查出來重復(fù)數(shù)據(jù),循環(huán)刪除。
emmmm,但是這個(gè)效率嘛,實(shí)在是太低了,1秒一條,重復(fù)數(shù)據(jù)大約2萬+,預(yù)估時(shí)間大約在8個(gè)小時(shí)左右。。。
盲目依靠前人的東西,而不去自己思考是有問題的!總?cè)ハ胫霸趺纯梢裕F(xiàn)在怎么不行了,這也是有問題的!我發(fā)現(xiàn),最近確實(shí)狀態(tài)不太對(duì),失去了探索和求知的欲望,今天算是一個(gè)警醒,頗有迷途知返的感覺。
言歸正傳,下面詳細(xì)介紹去重步驟。
CREATE?TABLE?`animal`?(
??`id`?int(11)?NOT?NULL?AUTO_INCREMENT,
??`name`?varchar(20)?DEFAULT?NULL,
??`age`?int(11)?DEFAULT?NULL,
??PRIMARY?KEY?(`id`)
)?ENGINE=InnoDB?AUTO_INCREMENT=1?DEFAULT?CHARSET=utf8?COLLATE=utf8_bin;
INSERT?INTO?`pilipa_dds`.`student`?(`id`,?`name`,?`age`)?VALUES?('1',?'cat',?'12');
INSERT?INTO?`pilipa_dds`.`student`?(`id`,?`name`,?`age`)?VALUES?('2',?'dog',?'13');
INSERT?INTO?`pilipa_dds`.`student`?(`id`,?`name`,?`age`)?VALUES?('3',?'camel',?'25');
INSERT?INTO?`pilipa_dds`.`student`?(`id`,?`name`,?`age`)?VALUES?('4',?'cat',?'32');
INSERT?INTO?`pilipa_dds`.`student`?(`id`,?`name`,?`age`)?VALUES?('5',?'dog',?'42');
目標(biāo):我們要去掉name相同的數(shù)據(jù)。
先看看哪些數(shù)據(jù)重復(fù)了
SELECT?name,count(?1?)?
FROM
?student?
GROUP?BY
NAME?
HAVING
?count(?1?)?>?1;
輸出:
name?count(1)?cat?2?dog?2
name為cat和dog的數(shù)據(jù)重復(fù)了,每個(gè)重復(fù)的數(shù)據(jù)有兩條;
Select?*?From?表?Where?重復(fù)字段?In?(Select?重復(fù)字段?From?表?Group?By?重復(fù)字段?Having?Count(1)>1)
刪除全部重復(fù)數(shù)據(jù),一條不留
直接刪除會(huì)報(bào)錯(cuò)
DELETE?
FROM
?student?
WHERE
?NAME?IN?(
?SELECT?NAME?
?FROM
??student?
?GROUP?BY
?NAME?
HAVING
?count(?1?)?>?1)
報(bào)錯(cuò):
1093?-?You?can't?specify?target?table?'student'?for?update?in?FROM?clause,?Time:?0.016000s
原因是:更新這個(gè)表的同時(shí)又查詢了這個(gè)表,查詢這個(gè)表的同時(shí)又去更新了這個(gè)表,可以理解為死鎖。mysql不支持這種更新查詢同一張表的操作
解決辦法:把要更新的幾列數(shù)據(jù)查詢出來做為一個(gè)第三方表,然后篩選更新。
DELETE?
FROM
?student?
WHERE
?NAME?IN?(
?SELECT
??t.NAME?
FROM
?(?SELECT?NAME?FROM?student?GROUP?BY?NAME?HAVING?count(?1?)?>?1?)?t)
刪除表中刪除重復(fù)數(shù)據(jù),僅保留一條
在刪除之前,我們可以先查一下,我們要?jiǎng)h除的重復(fù)數(shù)據(jù)是啥樣的
SELECT
?*?
FROM
?student?
WHERE
?id?NOT?IN?(
?SELECT
??t.id?
?FROM
?(?SELECT?MIN(?id?)?AS?id?FROM?student?GROUP?BY?`name`?)?t?
?)
啥意思呢,就是先通過name分組,查出id最小的數(shù)據(jù),這些數(shù)據(jù)就是我們要留下的火種,那么再查詢出id不在這里面的,就是我們要?jiǎng)h除的重復(fù)數(shù)據(jù)。
開始刪除重復(fù)數(shù)據(jù),僅留一條
很簡(jiǎn)單,剛才的select換成delete即可
DELETE?
FROM
?student?
WHERE
?id?NOT?IN?(
?SELECT
??t.id?
?FROM
?(?SELECT?MIN(?id?)?AS?id?FROM?student?GROUP?BY?`name`?)?t?
?)
90萬+的表執(zhí)行起來超級(jí)快。
All done ????????~
--------?THE END?--------
