公司面試題目之取出數據庫中重複的記錄

 公司面試題目之取出數據庫中重複的記錄

一道筆試題,就是查詢出數據表中重複的記錄,應該來說用過分組查尋的,這道題並不在話下,我們先來看看這張表

上圖高亮部分的是重複的數據行,那麼如何取出其中高亮的部分,
聚合函數
在解決這個問題前,我們必需先講講sql語言中一種特殊的函數:聚合函數,例如SUM, COUNT, MAX, AVG等。這些函數和其它函數的根本區別就是它們一般作用在多條記錄上。例如上函數從左至右依次爲 求總和,記錄數,最大值,平均值!關於它們的作用相信很多朋友也知道!但也有可能在自己知道的情況下,並不瞭解它們的學名,聚合函數。這也是我開篇寫這個的目的!
另外就是group by,分組查尋。看下面結果

通過使用GROUP BY 子句,可以讓SUM 這樣聚合函數對屬於一組的數據起作用。當我們上面指定 GROUP BY userName時,屬於同一個userName(用戶)的一組數據將只能返回一行值,也就是說,表中所有除userName(用戶)外的字段,只能通過 SUM, COUNT等聚合函數運算後返回一個值。假使我們在第二句SQL語句中添加一列,userPassword時,就會報如下錯誤

這應該是初學者經常遇見的錯誤,據上已經分析過,出現此種錯誤是必然,因爲,我們的結果是已經分組過的,所以結果會按姓名分組,相同的姓名只返回一行結果,但並沒有指定也按密碼分,所以當返回姓名重複記錄的時候,並不知道返回的這一行密碼取哪個?因爲我們沒有對密碼聚合,或分組,所以報錯是因爲密碼按此邏輯,無法取到!
那麼有朋友可以會想到那麼group by 後面再加上密碼會怎樣,可以試試。學計算機,有了想法就應該去嘗試,大膽嘗試。電腦也試不壞!怕什麼

此時程序有了結果。對比之前的圖,我們可以發現結果集不一樣了,多了一行
 a   15
變成了
a     a    10
a     b      5

想想原因,因爲我們現在 分組多加了密碼,所以也會按姓名和密碼都相同的分!因爲姓名都爲a的用戶有二個密碼爲a一個密碼爲b ,所以在按密碼分時,會繼續拆分!也就出現如上結果!

Having

那麼Having又是有什麼作用的?
 HAVING子句主要就是在聚合後對組記錄進行篩選。類似where,但其與where又是不同的!
讓我們還是通過具體的實例來理解GROUP BY 和 HAVING 子句
第二句,也即將登錄總次數大於5的記錄查出!注意在這裏,我們不能使用where,因爲用where來限定條件,需要符合條件的列必須在表中存在!而這裏的取出總登錄次數大於5,表中本沒有這樣一列,所以無法使用where來查詢,而必須使用having,瞭解這個,我們就應該知道where與having的差別了!
HAVING是對由sum或其它聚合函數運算結果的輸出進行限制
那麼在瞭解了上面的知識後,我們如何再來解決開篇提到的問題,也即如何取出表中重複的記錄?
我們要查出重複的記錄,那麼必然要用到分組查詢,group by。分組的依據爲表中各列。這樣它會將各列都相同的分爲一組,但同時我們要查詢出重複的記錄,因此必然需要相同的記錄至少應該是2條以上。由此可知。我們需要對group by 的結果進行限定,條件是記錄數大於1的,因此 我們聯想到having。因此有了如下解決方案:


那麼如果同時存在where及having是什麼樣的呢?看下圖:



還有另外一個相似的問題就是如何刪除數據庫中重複的記錄
這個問題應該有幾種解決方案,比較常用的是使用臨時表,如下:
--使用distinct關鍵字查出去重後的記錄,並將結果存儲在臨時表中
select distinct * into #temp from repeat   
--刪除 repeat 表
delete repeat   
--再從臨時表中取出所有結果放回repeat表中
insert repeat select * from #temp   
--刪除臨時表
drop table #temp

操作之後的結果與上,去掉了重複的行我用高亮做了標記。也即使用distinct關鍵字去重,是去掉所有列都相同的,而對於userName及userPassword相同的,它沒有處理出來,現在假設要將姓名與密碼都相同的也去掉,如何處理。看下面:

select *  from repeat a
where 
(a.userName ) 
in (select userName from repeat group by userName,userPassword having count(*> 1
and 
(a.userPassword ) 
in (select userPassword from repeat group by userName,userPassword having count(*> 1)

這樣取出的是用戶名與密碼相同的記錄!將select改爲delete即可刪除,當然,這樣刪除就全部刪除了,如果想要留一條,還可在後面加限定條件,來決定留下哪一條!

Stop talking and create the future !

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章