sql left join 去重_混入了一些奇怪的東西?SQL小技巧之資料去重
技術標籤:sql left join 去重sql sum 去重sql 去重並統計總數sql 去重查詢sql 去重求和sql 結果去重
大家好,歡迎踏入野生程式猿的生存之道,我是你們的老朋友大猿猿!
今天聊聊資料庫裡怎樣刪除重複資料。
“重複”的定義
首先咱先明確一下什麼叫重複資料,比如你有個表,好比說學生表吧,這個表裡出現了兩條一模一樣的資料,姓名、性別、出生日期、學號、等等等等,全都一樣,那麼這兩條資料就叫重複資料。當然,重複的也不一定是兩條,可能一個學生出現了20條,這20條都是重複的,或者張三出現了3條,李四出現了4條等等。
有主鍵
無主鍵
重複資料又可分為兩種情況,第一種是這個表連主鍵都沒有,所有欄位全重複。第二種是這個表有主鍵,除了主鍵外的其他欄位重複。
我們的目標
說到這裡大家應該瞭解了,本文裡的重複資料其實算是一種垃圾資料,它本不該出現,但由於各種原因,比如你導資料時重複操作了,比如你儲存按鈕沒做控制而又發生了連擊現象,等等等等。
那麼出現了重複資料,我們期望怎麼辦呢?當然是把多餘的刪掉,只保留一條。
解決辦法--有主鍵
我們先捋捋思路,假設某個重複資料有n條,那麼我們要刪掉n-1條,留下1條,而留下的這個“1”,其實和其他資料沒有任何區別,那麼我們怎麼定位出這個“1”呢?怎麼讓這個“1”和其他資料有所不同呢?說到這裡,應該有同學想到了,主鍵肯定不一樣!沒錯,我們就可以用主鍵區分,一不做二不休,我們就留主鍵最大的那個!直接上SQL:
delete from student T1 where id <> (select max(id) from student T2 where T1.name = T2.name and T1.age = T2.age and T1.gender = T2.gender and T1.national = T2.national and T1.addr = T2.addr)
為了保險起見,我們先把delete改成select *,看看要刪的內容是不是和我們預想的一樣:
可以看到,確實查出來的是重複的,且ID不是相同資料中最大的。我們執行delete,然後再看錶中資料:
可以看到,重複資料已經被刪除了。注意,例子中,張三隻有3條重複,另外一個張三隻是恰好重名而已,其他資訊不同。
解決辦法--無主鍵
方案一:
對於無主鍵的情況思路也是完全一樣,但是這裡出現問題了,沒有ID怎麼辦?大家不妨這樣想,雖然兩行資料一模一樣,但是資料庫自己卻能區分出誰是誰,那麼資料庫中肯定還有其他標識以供區分!比如oracle,就會有個隱藏欄位rowid。(如果你用的那個資料庫他偏偏就是沒有這麼個標識,那就只能先給這個表加一列,然後給這列賦值成一個自增序列)
我們先把這個欄位查出來看看它的真容:
select T.rowid,T.* from student T
雖然我們不知道rowid裡到底存的是啥意思,但可以肯定的一點是,它不會和別的行重複,於是我們剛才的那個sql只需改成這樣就行了:
delete from student T1 where rowid <> (select max(rowid) from student T2 where T1.name = T2.name and T1.age = T2.age and T1.gender = T2.gender and T1.national = T2.national and T1.addr = T2.addr)
方案二:
還有另一種方案,稍微笨一點。大家查詢時去除重複都知道怎麼寫吧?沒錯:
select distinct * from student
看結果:
那麼我們只需基於這個查詢新建個表,然後再把原來的表幹掉,最後再給新建的表改改名就OK啦:
create table student_temp as select distinct * from dy.student;drop table student;alter table student_temp rename to student;
為什麼說這個方案稍微笨一點呢?因為你建完表後,還要注意原表有沒有索引、許可權、觸發器等一系列相關的東西,如果有,你還得重新把這些東西建上。
好了小夥伴們,你學會了嗎?點我頭像能學習更多實用的開發小技巧,別忘了點關注哦~