mysql數據庫刪除重復的數據保留一條


1.問題引入

假設一個場景,一張用戶表,包含3個字段。id,identity_id,name。現在身份證號identity_id和姓名name有很多重復的數據,需要刪除只保留一條有效數據。

2.模擬環境

  • 1.登入mysql數據庫,創建一個單獨的測試數據庫mysql_exercise
create database mysql_exercise charset utf8;
  • 2.創建用戶表users
create table users(
                    id int auto_increment primary key,
                    identity_id varchar(20),
                    name varchar(20) not null
                   );

  • 3.插入測試數據
insert into users values(0,'620616199409206512','張三'),
                        (0,'620616199409206512','張三'),
                        (0,'62062619930920651X','李四'),
                        (0,'62062619930920651X','李四'),
                        (0,'620622199101206211','王五'),
                        (0,'620622199101206211','王五'),
                        (0,'322235199909116233','趙六');

可以多執行幾次,生成較多重復數據。

  • 4.解決思路
    (1)根據身份證號和name進行分組;
    (2)取出分組后的最大id(或最小id);
    (3)刪除除最大(或最小)id以外的其他字段;

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

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

報錯:

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

因為在MYSQL里,不能先select一個表的記錄,再按此條件進行更新和刪除同一個表的記錄。
解決辦法是,將select得到的結果,再通過中間表select一遍,這樣就規避了錯誤,
這個問題只出現於mysql,mssql和oracle不會出現此問題。

所以我們可以先將括號里面的sql語句先拿出來,先查到最大(或最小)id。

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

接着,又報錯了!!

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

意思是說:提示說每一個衍生出來的表,必須要有自己的別名!

執行子查詢的時候,外層查詢會將內層的查詢當做一張表來處理,所以我們需要給內層的查詢加上別名

 

繼續更正:
給查詢到的最大(或最小id)結果當做一張新的表,起別名t,並查詢t.mix_id

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

可以成功查到最大(或最小)id了,如下圖:

  • 6.第二次嘗試(成功!!!)
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
        );

執行結果:

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

3.拓展練習:刪除重復數據

編寫一個 SQL 查詢,來刪除 Person 表中所有重復的電子郵箱,重復的郵箱里只保留 Id 最小 的那個。

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

Id 是這個表的主鍵。
例如,在運行你的查詢語句之后,上面的 Person 表應返回以下幾行:

+----+------------------+
| 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;

 

 

參考文章:

https://blog.csdn.net/qq_38923792/article/details/95240733


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM