MySQL 過濾重復(fù)數(shù)據(jù)
我們提供的服務(wù)有:網(wǎng)站設(shè)計制作、網(wǎng)站設(shè)計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、揚中ssl等。為上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的揚中網(wǎng)站制作公司
有些 MySQL 數(shù)據(jù)表中可能存在重復(fù)的記錄,有些情況我們允許重復(fù)數(shù)據(jù)的存在,但有時候我們也需要刪除這些重復(fù)的數(shù)據(jù)。
如果你需要讀取不重復(fù)的數(shù)據(jù)可以在 SELECT 語句中使用 DISTINCT 關(guān)鍵字來過濾重復(fù)數(shù)據(jù)。
from 樹懶學(xué)堂- 一站式數(shù)據(jù)知識學(xué)習(xí)平臺
你也可以使用 GROUP BY 來讀取數(shù)據(jù)表中不重復(fù)的數(shù)據(jù):
mysql數(shù)據(jù)表中有多條重復(fù)數(shù)據(jù)記錄,現(xiàn)在想刪除刪除部分重復(fù)數(shù)據(jù),保留最后一條更新或者插入的數(shù)據(jù)。
以學(xué)生表為例,我們創(chuàng)建一個簡單的數(shù)據(jù)表來做實驗:
往表里面插入一些實驗數(shù)據(jù):
我們可以根據(jù)分組查詢先將重復(fù)數(shù)據(jù)查詢出來,同時也可以獲取到最后的更新時間,然后再與原表聯(lián)表查詢小于最大時間的數(shù)據(jù),將查詢出來的數(shù)據(jù)刪除。
------先來慢慢消化-------
在做刪除前,我們可以先看看有哪些數(shù)據(jù)是有重復(fù)的:
可以看到張三,李四,王五的數(shù)據(jù)是有重復(fù)的,趙六沒有重復(fù),下面我們查找最后更新的記錄。
可以看到,最后更新的數(shù)據(jù)為15:57:46的記錄沒有在結(jié)果中。
可以看到重復(fù)記錄已經(jīng)被清理掉。
假如有兩行記錄是完全一樣的,這個方法就不可行了,往表里面在跑一次數(shù)據(jù)插入:
執(zhí)行刪除計劃:
創(chuàng)建一個臨時表存放最后插入的一條數(shù)據(jù)(包含重復(fù)與沒有重復(fù)的),然后清空原表,再將臨時表的數(shù)據(jù)復(fù)制到原表中,最后把臨時表刪除。
這個很好理解,相當(dāng)于ctrl+c,ctrl+v的操作,數(shù)據(jù)表如下:
這樣數(shù)據(jù)去重就完成了,需要注意的是, 如果表數(shù)據(jù)量很大,注意在group by 里面的字段建立索引,同時,生產(chǎn)環(huán)境注意好先進(jìn)行數(shù)據(jù)備份操作 。
首先是將數(shù)據(jù)庫里邊的重復(fù)記錄刪掉,我看網(wǎng)上有好多答案是這樣的:
1 delete from people
2 where peopleId in (select peopleId from people group by peopleId having count(peopleId) 1)
3 and rowid not in (select min(rowid) from people group by peopleId having count(peopleId )1)
但其實我每次運行這條語句都是行不通的,會報錯:
SQL 錯誤 [1093] [HY000]: You can't specify target table 'test1' for update in FROM clause
java.sql.SQLException: You can't specify target table 'test1' for update in FROM clause
去網(wǎng)上查過好像是說update以及delete操作沒辦法跟查詢操作一起做的,我看過有的更新的跟查詢的一起做的好像是給查出來的那部分起個別名,然后進(jìn)行更新就可以了,但是刪除這個我起了別名也不對,不知道是我寫錯還是不行,我就跳過這個方法了。
我用的方法是:先查出數(shù)據(jù)庫中的重復(fù)記錄的數(shù)據(jù)中的一條,這個不難,很簡單的,sql語句如下:
select * from test1 where name in (select ?name from test1 ?group ?by ?name ? having ?count(name) 1)
and id in (select min(id) from ?test1 ?group by name ?having count(name)1)
結(jié)果如下:
id |name |phont |
---|--------|-------|
1 |name22 |123 |
3 |name222 |123 |
5 |name2 |123123 |
8 |123 |123123 |
11 |name1 |123123 |
13 |111 |1231 |
14 |112 |1232 |
這些都是不重復(fù)的,換句話說都是要保留的,不被刪掉的,而其余與這些結(jié)果中name相同的應(yīng)該被刪掉。
也就是說將上邊那個sql語句id后邊加一個not ,查出來的結(jié)果就是要刪掉的:結(jié)果如下
id |name |phont |
---|--------|-------|
2 |name22 |123 |
4 |name222 |123 |
6 |name2 |123123 |
7 |name2 |NULL |
9 |123 |123123 |
10 |123 |123123 |
12 |name1 |123123 |
15 |111 |1233 |
16 |112 |1234 |
17 |111 |1235 |
18 |112 |1236 |
我把這些需要刪掉的存到另外一個表里,然后我新建一個test2表,結(jié)構(gòu)復(fù)制test1的結(jié)構(gòu)就好了
1 CREATE TABLE `test2` (2 ? `id` int(11) NOT NULL AUTO_INCREMENT,3 ? `name` varchar(50) DEFAULT NULL,4 ? `phont` varchar(50) DEFAULT NULL,5 ? PRIMARY KEY (`id`)6 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
然后插入語句是:
1 insert into test2(2 select * from test.test1 where name in (select ?name from test.test1 ?group ?by ?name ? having ?count(name) 1)
3 and id not in (select min(id) from ?test.test1 ?group by name ?having count(name)1)
4 )
然后test2的表里的數(shù)據(jù)就是下圖這樣的:
那接下來做的就是刪掉test1表里邊與test2表的id相同的數(shù)據(jù)。
1 delete a.* from test1 a, test2 b where a.id = b.id ;
這樣,test1里邊的數(shù)據(jù)就變成了:
這樣的結(jié)果就是完全不重復(fù)的,但是我還想要他們的id是連續(xù)的,而不是這樣的斷開的。
我的做法是將這個表的除掉id之外的所有字段查出插入到另外一個表test3中,當(dāng)然,test3要設(shè)置id為自增主鍵,但是不插入id,讓它自增,就連續(xù)了
當(dāng)然要新建表test3啦,不過把上邊新建的test2那個復(fù)制下來改名字為test3就好啦。
然后插入:
1 insert into test3(name, phont)2 (select name, phont from test2)
test3表里的結(jié)果就是:
這樣就可以把test3改成你想要的名字,然后刪掉test1和test2了,大功告成~
不過感覺還可以就是將已經(jīng)刪掉重復(fù)數(shù)據(jù)的表test1的數(shù)據(jù)全都導(dǎo)出來,一般的數(shù)據(jù)庫連接工具都有這樣的功能,導(dǎo)成sql格式的,然后新建一個表,比test1多增一個自增主鍵字段叫NewId字段,但是Id字段不能再自增了,然后將導(dǎo)成的sql文件導(dǎo)入,不過那個sql文件可能要編輯一下,改一下自增主鍵id變?yōu)槠胀ǖ淖侄问裁吹?,然后到新表了之后,刪掉id字段,修改NewId為Id,應(yīng)該也可以,但是這個方法我沒試過,原先預(yù)想過要這么做但是沒有這么做,估計以后可以試試,但是感覺兩種的麻煩程度都差不多啊,但是如果將sql語句寫下來之后可能還是第一種方法比較快一點吧。
MYSQL里有五百萬數(shù)據(jù),但大多是重復(fù)的,真實的就180萬,于是想怎樣把這些重復(fù)的數(shù)據(jù)搞出來,在網(wǎng)上找了一圈,好多是用NOT IN這樣的代碼,這樣效率很低,自己琢磨組合了一下,找到一個高效的處理方式,用這個方式,五百萬數(shù)據(jù),十來分鐘就全部去除重復(fù)了,請各位參考。
第一步:從500萬數(shù)據(jù)表data_content_152里提取出不重復(fù)的字段SFZHM對應(yīng)的ID字段到TMP3表
1 create table tmp3 as select min(id) as col1 from data_content_152 group by SFZHM;
第二步:創(chuàng)建新表RES
1234 CREATE TABLE `res` (`id` int(11),`sfz` char(20)) ENGINE=MyISAM;
第三步:把TMP3表ID對應(yīng)到data_content_152里需要提取的數(shù)據(jù)添加到RES表的SFZ字段
1 INSERT INTO res (sfz) SELECT sfzhm FROM data_content_152,tmp3 where data_content_152.id=tmp3.col1
至此,就在MYSQL里實現(xiàn)了,給數(shù)據(jù)表data_content_152完全刪除重復(fù)數(shù)據(jù),把去重復(fù)后的數(shù)據(jù)導(dǎo)入到RES表。
MySQL 刪除重復(fù)數(shù)據(jù)
有些 MySQL 數(shù)據(jù)表中可能存在重復(fù)的記錄,有些情況我們允許重復(fù)數(shù)據(jù)的存在,但有時候我們也需要刪除這些重復(fù)的數(shù)據(jù)。
本章節(jié)我們將為大家介紹如何防止數(shù)據(jù)表出現(xiàn)重復(fù)數(shù)據(jù)及如何刪除數(shù)據(jù)表中的重復(fù)數(shù)據(jù)。
刪除重復(fù)數(shù)據(jù)
如果你想刪除數(shù)據(jù)表中的重復(fù)數(shù)據(jù),你可以使用以下的SQL語句:
from 樹懶學(xué)堂 - 一站式數(shù)據(jù)知識平臺
當(dāng)然你也可以在數(shù)據(jù)表中添加 INDEX(索引) 和 PRIMAY KEY(主鍵)這種簡單的方法來刪除表中的重復(fù)記錄。方法如下: