溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

發(fā)布時(shí)間:2021-03-09 15:58:50 來(lái)源:億速云 閱讀:383 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

本篇文章為大家展示了怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù),內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

1.問(wèn)題引入

假設(shè)一個(gè)場(chǎng)景,一張用戶表,包含3個(gè)字段。id,identity_id,name?,F(xiàn)在身份證號(hào)identity_id和姓名name有很多重復(fù)的數(shù)據(jù),需要?jiǎng)h除只保留一條有效數(shù)據(jù)。

2.模擬環(huán)境

1.登入mysql數(shù)據(jù)庫(kù),創(chuàng)建一個(gè)單獨(dú)的測(cè)試數(shù)據(jù)庫(kù)mysql_exercise

create database mysql_exercise charset utf8;

2.創(chuàng)建用戶表users

create table users(
					id int auto_increment primary key,
					identity_id varchar(20),
					name varchar(20) not null
     );

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

3.插入測(cè)試數(shù)據(jù)

insert into users values(0,'620616199409206512','張三'),
						(0,'620616199409206512','張三'),
						(0,'62062619930920651X','李四'),
						(0,'62062619930920651X','李四'),
						(0,'620622199101206211','王五'),
						(0,'620622199101206211','王五'),
						(0,'322235199909116233','趙六');

可以多執(zhí)行幾次,生成較多重復(fù)數(shù)據(jù)。

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

4.解決思路

(1)根據(jù)身份證號(hào)和name進(jìn)行分組;

(2)取出分組后的最大id(或最小id);

(3)刪除除最大(或最小)id以外的其他字段;

5.第一次嘗試(失敗!!!)

delete from users where id not in (select max(id) from users group by identity_id,name);

報(bào)錯(cuò):

1093 (HY000): You can't specify target table 'users' for update in FROM clause

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

因?yàn)樵贛YSQL里,不能先select一個(gè)表的記錄,再按此條件進(jìn)行更新和刪除同一個(gè)表的記錄。

解決辦法是,將select得到的結(jié)果,再通過(guò)中間表select一遍,這樣就規(guī)避了錯(cuò)誤,

這個(gè)問(wèn)題只出現(xiàn)于mysql,mssql和oracle不會(huì)出現(xiàn)此問(wèn)題。

所以我們可以先將括號(hào)里面的sql語(yǔ)句先拿出來(lái),先查到最大(或最?。﹊d。

select max_id from (select max(id) as max_id from users group by identity_id,name);

接著,又報(bào)錯(cuò)了?。?!

ERROR 1248 (42000): Every derived table must have its own alias

意思是說(shuō):提示說(shuō)每一個(gè)衍生出來(lái)的表,必須要有自己的別名!

執(zhí)行子查詢(xún)的時(shí)候,外層查詢(xún)會(huì)將內(nèi)層的查詢(xún)當(dāng)做一張表來(lái)處理,所以我們需要給內(nèi)層的查詢(xún)加上別名

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

繼續(xù)更正:

給查詢(xún)到的最大(或最小id)結(jié)果當(dāng)做一張新的表,起別名t,并查詢(xún)t.mix_id。

select t.max_id from (select max(id) as max_id from users group by identity_id,name) as t;

可以成功查到最大(或最?。﹊d了,如下圖:

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

6.第二次嘗試(成功?。。。?/strong>

delete from users where id not in (
		select t.max_id from 
		(select max(id) as max_id from users group by identity_id,name) as t
		);

執(zhí)行結(jié)果:

怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù)

成功將重復(fù)的數(shù)據(jù)刪除,只保留了最后一次增加的記錄。同理也可以保留第一次添加的記錄(即刪除每個(gè)分組里面除最小id以外的其他條記錄)

3.知識(shí)拓展一:更新數(shù)據(jù)

其他場(chǎng)景應(yīng)用:要將用戶表user_info里名字(name)為空字符串("")的用戶的狀態(tài)(status)改成"0"

update user_info set status='0' where user_id in (select user_id from user_info where name='')

同樣報(bào)了如下錯(cuò)誤:

You can't specify target table ‘user_info' for update in FROM clause

因?yàn)樵贛YSQL里,不能先select一個(gè)表的記錄,再按此條件進(jìn)行更新和刪除同一個(gè)表的記錄,解決辦法是,將select得到的結(jié)果,再通過(guò)中間表select一遍,這樣就規(guī)避了錯(cuò)誤。
以下兩種均可?。?!

update user_info set status='0' where user_id in 
	 (select user_id from (select user_id from user_info where name = '') t1);

下面這種也可,細(xì)微差別,別名可帶as可不帶,t1.user_id 直接和內(nèi)層的user_id對(duì)應(yīng)也可以。

update user_info set status='0' where user_id in 
	(select t1.user_id from (select user_id from user_info where name='') as t1);

3.1 分步驟解析

(1)將以下查詢(xún)結(jié)果作為中間表:

select user_id from user_info where name='';

(2)再查詢(xún)一遍中間表作為結(jié)果集:

select user_id from (select user_id from user_info where name='') as t;

(3)更新數(shù)據(jù)

update user_info set status='0' where user_id in 
	(select user_id from (select user_id from user_info where name='') as t1);

4.拓展練習(xí):刪除重復(fù)數(shù)據(jù)

編寫(xiě)一個(gè) SQL 查詢(xún),來(lái)刪除 Person 表中所有重復(fù)的電子郵箱,重復(fù)的郵箱里只保留 Id 最小 的那個(gè)。

+----+------------------+
| Id | Email      |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
+----+------------------+

Id 是這個(gè)表的主鍵。

例如,在運(yùn)行你的查詢(xún)語(yǔ)句之后,上面的 Person 表應(yīng)返回以下幾行:

+----+------------------+
| Id | Email      |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+

解答一:

delete from Person where Id not in (
	select t.min_id from (
		select min(Id) as min_id from Person group by Email
		) as t
	);

解答二:

delete p1 from 
	Person as p1,Person as p2 
		where p1.Email=p2.Email and p1.Id > p2.Id;

上述內(nèi)容就是怎么在mysql數(shù)據(jù)庫(kù)中刪除重復(fù)的數(shù)據(jù),你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI