點擊上方 java項目開發,選擇 設爲星標前端
優質項目,及時送達vue
-----java
做者:千gmysql
blog.csdn.net/n950814abc/article/details/82284838react
最近在作題庫系統,因爲在題庫中添加了重複的試題,因此須要查詢出重複的試題,而且刪除掉重複的試題只保留其中1條,以保證考試的時候抽不到重複的題。web
首先寫了一個小的例子:面試
1、單個字段的操做
這是數據庫中的表:spring

分組介紹:

Select 重複字段 From 表 Group By 重複字段 Having Count(*)>1
查看是否有重複的數據:sql
-
GROUP BY <列名序列>數據庫
-
HAVING <組條件表達式>
查詢出:根據dname分組,同時知足having字句中組條件表達式(重複次數大於1)的那些組
count(*)與count(1) 其實沒有什麼差異,用哪一個均可以
count(*)與count(列名)的區別:
count(*)將返回表格中全部存在的行的總數包括值爲null的行,然而count(列名)將返回表格中除去null之外的全部行的總數(有默認值的列也會被計入)
1. 查詢所有重複的數據:

Select * From 表 Where 重複字段 In (Select 重複字段 From 表 Group By 重複字段 Having Count(*)>1)
2. 刪除所有重複試題:
將上面的查詢select改成delete(這樣會出錯的)
DELETE
FROM
dept
WHERE
dname IN (
SELECT
dname
FROM
dept
GROUP BY
dname
HAVING
count(1) > 1
)
會出現以下錯誤:[Err] 1093 - You can't specify target table 'dept' for update in FROM clause
緣由是:更新這個表的同時又查詢了這個表,查詢這個表的同時又去更新了這個表,能夠理解爲死鎖。mysql不支持這種更新查詢同一張表的操做
解決辦法:把要更新的幾列數據查詢出來作爲一個第三方表,而後篩選更新。

3. 查詢表中多餘重複試題(根據depno來判斷,除了rowid最小的一個)
a. 第一種方法:

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. 第二種方法:
☆根據dname分組,查找出deptno最小的。而後再查找deptno不包含剛纔查出來的。這樣就查詢出了全部的重複數據(除了deptno最小的那行)。搜索Java知音公衆號,回覆「後端面試」,送你一份Java面試題寶典.pdf
SELECT *
FROM
dept
WHERE
deptno NOT IN (
SELECT
dt.minno
FROM
(
SELECT
MIN(deptno) AS minno
FROM
dept
GROUP BY
dname
) dt
)
c. 補充第三種方法:
SELECT
*
FROM
table_name AS ta
WHERE
ta.惟一鍵 <> ( SELECT max( tb.惟一鍵 ) FROM table_name AS tb WHERE ta.判斷重複的列 = tb.判斷重複的列 );
4. 刪除表中多餘重複試題而且只留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. ☆第二種方法(與上面查詢的第二種方法對應,只是將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. 補充第三種方法(評論區推薦的一種方法):
DELETE
FROM
table_name AS ta
WHERE
ta.惟一鍵 <> (
SELECT
t.maxid
FROM
( SELECT max( tb.惟一鍵 ) AS maxid FROM table_name AS tb WHERE ta.判斷重複的列 = tb.判斷重複的列 ) t
);
雙11了,今天開始,限量秒殺
1核2G,1年62元,3年200元,秒殺
1核2G,1年62元,3年200元,秒殺
1核2G,1年62元,3年200元,秒殺
2、多個字段的操做:
單個字段的若是會了,多個字段也很是簡單。就是將group by 的字段增長爲你想要的便可。搜索Java知音公衆號,回覆「後端面試」,送你一份Java面試題寶典.pdf
此處只寫一個,其餘方法請仿照一個字段的寫便可。
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
)
總結:
其實上面的方法還有不少須要優化的地方,若是數據量太大的話,執行起來很慢,能夠考慮加優化一下:
-
在常常查詢的字段上加上索引
-
將*改成你須要查詢出來的字段,不要所有查詢出來
-
小表驅動大表用IN,大表驅動小表用EXISTS。IN適合的狀況是外表數據量小的狀況,而不是外表數據大的狀況,由於IN會遍歷外表的所有數據,假設a表100條,b表10000條那麼遍歷次數就是100*10000次,而exists則是執行100次去判斷a表中的數據是否在b表中存在,它只執行了a.length次數。至於哪個效率高是要看狀況的,由於in是在內存中比較的,而exists則是進行數據庫查詢操做的
推薦案例
溫暖提示

請長按識別二維碼
想學習更多的java功能案例請關注
Java項目開發


若是你以爲這個案例以及咱們的分享思路不錯,對你有幫助,請分享給身邊更多須要學習的朋友。別忘了《留言+點在看》給做者一個鼓勵哦!
本文分享自微信公衆號 - web項目開發(javawebkaifa)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。