<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何實(shí)現(xiàn) MySQL 刪除重復(fù)記錄并且只保留一條

          共 3223字,需瀏覽 7分鐘

           ·

          2020-10-25 10:23

          程序員的成長(zhǎng)之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注


          閱讀本文大概需要 4 分鐘。

          作者:千g
          blog.csdn.net/n950814abc/article/details/82284838
          最近在做題庫(kù)系統(tǒng),由于在題庫(kù)中添加了重復(fù)的試題,所以需要查詢出重復(fù)的試題,并且刪除掉重復(fù)的試題只保留其中1條,以保證考試的時(shí)候抽不到重復(fù)的題。
          首先寫(xiě)了一個(gè)小的例子:

          一、單個(gè)字段的操作

          這是數(shù)據(jù)庫(kù)中的表:

          分組介紹

          Select 重復(fù)字段 FromGroup By 重復(fù)字段 Having Count(*)>1
          查看是否有重復(fù)的數(shù)據(jù):
          • GROUP BY <列名序列>

          • HAVING <組條件表達(dá)式>

          查詢出:根據(jù)dname分組,同時(shí)滿足having字句中組條件表達(dá)式(重復(fù)次數(shù)大于1)的那些組
          count(*)與count(1)?其實(shí)沒(méi)有什么差別,用哪個(gè)都可以
          count(*)與count(列名)的區(qū)別:
          count(*)將返回表格中所有存在的行的總數(shù)包括值為null的行,然而count(列名)將返回表格中除去null以外的所有行的總數(shù)(有默認(rèn)值的列也會(huì)被計(jì)入)。

          1. 查詢?nèi)恐貜?fù)的數(shù)據(jù)



          Select * FromWhere 重復(fù)字段 In (Select 重復(fù)字段 FromGroup By 重復(fù)字段 Having Count(*)>1)


          2. 刪除全部重復(fù)試題

          將上面的查詢select改為delete(這樣會(huì)出錯(cuò)的)
          DELETEFROM deptWHERE dname IN (  SELECT   dname  FROM   dept  GROUP BY   dname  HAVING   count(1) > 1 )
          會(huì)出現(xiàn)如下錯(cuò)誤:[Err] 1093 - You can't specify target table 'dept' for update in FROM clause
          原因是:更新這個(gè)表的同時(shí)又查詢了這個(gè)表,查詢這個(gè)表的同時(shí)又去更新了這個(gè)表,可以理解為死鎖。mysql不支持這種更新查詢同一張表的操作
          解決辦法:把要更新的幾列數(shù)據(jù)查詢出來(lái)做為一個(gè)第三方表,然后篩選更新。


          3. 查詢表中多余重復(fù)試題(根據(jù)depno來(lái)判斷,除了rowid最小的一個(gè))

          a. 第一種方法

          SELECT *FROM deptWHERE dname IN (  SELECT   dname  FROM   dept  GROUP BY   dname  HAVING   COUNT(1) > 1 )AND deptno NOT IN ( SELECT  MIN(deptno) FROM  dept GROUP BY  dname HAVING  COUNT(1) > 1)
          上面這種寫(xiě)法正確,但是查詢的速度太慢,可以試一下下面這種方法:

          b. 第二種方法

          根據(jù)dname分組,查找出deptno最小的。然后再查找deptno不包含剛才查出來(lái)的。這樣就查詢出了所有的重復(fù)數(shù)據(jù)(除了deptno最小的那行)
          SELECT *FROM deptWHERE deptno NOT IN (  SELECT   dt.minno  FROM   (    SELECT     MIN(deptno) AS minno    FROM     dept    GROUP BY     dname   ) dt )

          c. 補(bǔ)充第三種方法

          SELECT * FROM table_name AS ta WHERE ta.唯一鍵 <> ( SELECT max( tb.唯一鍵 ) FROM table_name AS tb WHERE ta.判斷重復(fù)的列 = tb.判斷重復(fù)的列 );


          4. 刪除表中多余重復(fù)試題并且只留1條

          a. 第一種方法:

          DELETEFROM deptWHERE dname IN (  SELECT   t.dname  FROM   (    SELECT     dname    FROM     dept    GROUP BY     dname    HAVING     count(1) > 1   ) t )AND deptno NOT IN (SELECT dt.mindeptnoFROM (  SELECT   min(deptno) AS mindeptno  FROM   dept  GROUP BY   dname  HAVING   count(1) > 1 ) dt)

          b. 第二種方法(與上面查詢的第二種方法對(duì)應(yīng),只是將select改為delete)

          DELETEFROM deptWHERE deptno NOT IN (  SELECT   dt.minno  FROM   (    SELECT     MIN(deptno) AS minno    FROM     dept    GROUP BY     dname   ) dt )

          c. 補(bǔ)充第三種方法(評(píng)論區(qū)推薦的一種方法)

          DELETE FROM table_name AS ta WHERE ta.唯一鍵 <> (SELECT t.maxid FROM ( SELECT max( tb.唯一鍵 ) AS maxid FROM table_name AS tb WHERE ta.判斷重復(fù)的列 = tb.判斷重復(fù)的列 ) t  );

          二、多個(gè)字段的操作

          單個(gè)字段的如果會(huì)了,多個(gè)字段也非常簡(jiǎn)單。就是將group by 的字段增加為你想要的即可。
          此處只寫(xiě)一個(gè),其他方法請(qǐng)仿照一個(gè)字段的寫(xiě)即可。
          DELETEFROM deptWHERE (dname, db_source) IN (  SELECT   t.dname,   t.db_source  FROM   (    SELECT     dname,     db_source    FROM     dept    GROUP BY     dname,     db_source    HAVING     count(1) > 1   ) t )AND deptno NOT IN ( SELECT  dt.mindeptno FROM  (   SELECT    min(deptno) AS mindeptno   FROM    dept   GROUP BY    dname,    db_source   HAVING    count(1) > 1  ) dt)

          總結(jié)

          其實(shí)上面的方法還有很多需要優(yōu)化的地方,如果數(shù)據(jù)量太大的話,執(zhí)行起來(lái)很慢,可以考慮加優(yōu)化一下:
          • 在經(jīng)常查詢的字段上加上索引

          • 將*改為你需要查詢出來(lái)的字段,不要全部查詢出來(lái)

          • 小表驅(qū)動(dòng)大表用IN,大表驅(qū)動(dòng)小表用EXISTS。IN適合的情況是外表數(shù)據(jù)量小的情況,而不是外表數(shù)據(jù)大的情況,因?yàn)镮N會(huì)遍歷外表的全部數(shù)據(jù),假設(shè)a表100條,b表10000條那么遍歷次數(shù)就是100*10000次,而exists則是執(zhí)行100次去判斷a表中的數(shù)據(jù)是否在b表中存在,它只執(zhí)行了a.length次數(shù)。至于哪一個(gè)效率高是要看情況的,因?yàn)閕n是在內(nèi)存中比較的,而exists則是進(jìn)行數(shù)據(jù)庫(kù)查詢操作的


          別忘記點(diǎn)個(gè)在看,咱們下篇見(jiàn)

          每天進(jìn)步一點(diǎn)點(diǎn)
          慢一點(diǎn)才能更快

          推薦閱讀:

          給新手的 11 個(gè) Docker 免費(fèi)上手項(xiàng)目

          阿里云網(wǎng)盤(pán)開(kāi)啟公測(cè)!不限速、2T永久免費(fèi)空間!!

          經(jīng)過(guò)學(xué)習(xí)摸索,由我主筆的公眾號(hào):碼農(nóng)秘籍,現(xiàn)已正式上線!接下來(lái),我會(huì)在該公眾號(hào)上,為大家分享投資理財(cái)?shù)男≈R(shí),感興趣的小伙伴可以關(guān)注一下!

          微信掃描二維碼,關(guān)注我的公眾號(hào)

          朕已閱?

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产ts在线 | 国产黄色三级片 | www.168亚洲毛片基地 | 含羞草视频一区二区三区在线无码 | 内射毛片在线免费看 |