最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄

 更新時(shí)間:2023年01月04日 08:29:08   作者:?平凡?  
本文主要介紹了MySQL中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近在做題庫系統(tǒng),由于在題庫中添加了重復(fù)的試題,所以需要查詢出重復(fù)的試題,并且刪除掉重復(fù)的試題只保留其中1條,以保證考試的時(shí)候抽不到重復(fù)的題。

首先寫了一個(gè)小的例子:

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

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

如何實(shí)現(xiàn) MySQL 中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄_字段_02

分組介紹

如何實(shí)現(xiàn) MySQL 中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄_字段_03

Select 重復(fù)字段 From 表 Group By 重復(fù)字段 Having Count(*)>1

查看是否有重復(fù)的數(shù)據(jù):

  • GROUP BY <列名序列>
  • HAVING <組條件表達(dá)式>

查詢出:根據(jù)dname分組,同時(shí)滿足having字句中組條件表達(dá)式(重復(fù)次數(shù)大于1)的那些組

count(*)與count(1)其實(shí)沒有什么差別,用哪個(gè)都可以

count(*)與count(列名)的區(qū)別:

count(*)將返回表格中所有存在的行的總數(shù)包括值為null的行,然而count(列名)將返回表格中除去null以外的所有行的總數(shù)(有默認(rèn)值的列也會(huì)被計(jì)入)

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

如何實(shí)現(xiàn) MySQL 中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄_數(shù)據(jù)_04

Select * From 表 Where 重復(fù)字段 In (Select 重復(fù)字段 From 表 Group By 重復(fù)字段 Having Count(*)>1)

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

將上面的查詢select改為delete(這樣會(huì)出錯(cuò)的)

DELETE
FROM
 dept
WHERE
 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ù)查詢出來做為一個(gè)第三方表,然后篩選更新。

如何實(shí)現(xiàn) MySQL 中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄_數(shù)據(jù)_05

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

a. 第一種方法:

如何實(shí)現(xiàn) MySQL 中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄_數(shù)據(jù)_06

SELECT
 *
FROM
 dept
WHERE
 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
)

上面這種寫法正確,但是查詢的速度太慢,可以試一下下面這種方法:

b. 第二種方法:

☆根據(jù)dname分組,查找出deptno最小的。然后再查找deptno不包含剛才查出來的。這樣就查詢出了所有的重復(fù)數(shù)據(jù)(除了deptno最小的那行)。

SELECT *
FROM
 dept
WHERE
 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. 第一種方法:

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

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

DELETE
FROM
 dept
WHERE
 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 的字段增加為你想要的即可。

此處只寫一個(gè),其他方法請(qǐng)仿照一個(gè)字段的寫即可。

DELETE
FROM
 dept
WHERE
 (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í)行起來很慢,可以考慮加優(yōu)化一下:

  • 在經(jīng)常查詢的字段上加上索引
  • 將*改為你需要查詢出來的字段,不要全部查詢出來
  • 小表驅(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ù)庫查詢操作的

到此這篇關(guān)于MySQL中通過SQL語句刪除重復(fù)記錄并且只保留一條記錄的文章就介紹到這了,更多相關(guān)MySQL SQL語句刪除重復(fù)記錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

循化| 会泽县| 陆良县| 横山县| 横山县| 合川市| 汕尾市| 蒙城县| 海淀区| 景德镇市| 黄山市| 梁河县| 襄垣县| 奉贤区| 中方县| 镇远县| 延安市| 无锡市| 延吉市| 茶陵县| 奇台县| 宝山区| 木里| 伊宁县| 石屏县| 南溪县| 博白县| 衡山县| 宝坻区| 慈利县| 杭锦后旗| 运城市| 光山县| 兴安县| 南澳县| 高尔夫| 安乡县| 贵州省| 迁安市| 左云县| 通化县|