2012-07-12 60 views
0

關於如何在數據庫中查找重複內容有很多問題,但沒有解決具體問題。如何在數據庫中查找重複項?

我有一個約表。 120000個條目。我需要找到重複的。爲了找到他們,我用一個PHP腳本的結構如下所示:

//get all entries from database 
//loop through them 
    //get entries with greater id 
    //compare all of them with the original one 
    //update database (delete duplicate, update information in linked tables, etc.) 

它不可能在最初的查詢已經整理出所有重複,因爲我經歷了,因爲我重複的搜索中的所有條目必須循環不僅對100%相同的條目敏感,而且對90%相同的條目也很敏感。我使用了similar_text()。

我認爲第一個循環沒問題,但循環循環內的所有其他條目太多了。有120000個條目,這將接近(120000^2)/ 2次迭代。

因此,不要在循環中使用循環,而必須有更好的方法來做到這一點。你有什麼想法?我想過使用in_array(),但它對90%字符串相似性這樣的東西不敏感,也沒有給我數組的字段找到重複項 - 我需要那些獲得條目的id來更新數據庫正確。

任何想法?

非常感謝!

查爾斯

更新1

我使用的是現在的查詢如下:

SELECT a.host_id 
FROM host_webs a 
JOIN host_webs b ON a.host_id != b.host_id AND a.web = b.web 
GROUP BY a.host_id 

這表明原件及複印件完美,但我需要擺脫原件,即與相關數據一起找到的第一個。我怎麼能做到這一點?

回答

2

可以JOIN表到自身,做這一切在SQL(我知道你SA你不認爲你可以,但如果是這種情況,我會感到驚訝)。您需要做的就是將所有用於測試重複項的列放入JOINON子句中。

SELECT id 
FROM tablename a 
JOIN tablename b ON a.id != b.id AND a.col1 = b.col1 AND a.col2 = b.col2 
GROUP BY id 

這將只返回id S其中col1col2是重複的行。您可以將所需的任何字符串比較合併到此中,ON子句可以像您需要的那樣複雜。例如:

SELECT id 
FROM tablename a 
JOIN tablename b ON a.id != b.id AND 
    (a.col1 = b.col1 AND (a.col2 = b.col2 OR a.col3 = b.col3)) 
    OR ((a.col1 = b.col1 OR a.col2 = b.col2) AND a.col3 = b.col3) 
    OR (SOUNDEX(a.col1) = SOUNDEX(b.col1) AND SOUNDEX(a.col2) = SOUNDEX(b.col2) AND SOUNDEX(a.col3) = SOUNDEX(b.col3)) 
GROUP BY id 

編輯

因爲所有你實際上是與您的查詢是尋找行,其中的web列是相同這樣做,這將做只發現重複的,而不是的工作原來的「良」的記載 - 假設host_id是數字和「好」的記錄將是一個具有最低host_id

SELECT b.host_id 
FROM host_webs a 
INNER JOIN host_webs b ON b.web = a.web AND b.host_id > a.host_id 
GROUP BY b.host_id 

我意馬NE比賽結束這裏將刪除重複的,所以如果你感覺勇敢的你實際上可以一次性刪除:

DELETE b.* 
FROM host_webs a 
INNER JOIN host_webs b ON b.web = a.web AND b.host_id > a.host_id 

GROUP BY不在DELETE語句,因爲它並不重要,如果有必要您嘗試在單個語句中多次刪除同一行。

+0

謝謝!查詢容忍90%的相似性嗎? – weltschmerz 2012-07-12 22:48:04

+0

@Charles它取決於你如何定義90% - 這就是第二個例子。這返回至少兩個'col1','col2','col3'是相同或相同的列都具有相同的soundex得分的行。您使用的確切查詢用例取決於列類型和用於確定相似性的標準。 – DaveRandom 2012-07-12 22:51:30

+0

我正在嘗試使用你的第一個解決方案,但它帶來了一個問題:它不僅給我找到的重複項,而且還給出了原始的重複項。我該怎麼做才能使它不顯示原件?注意:可以有多個重複。查看我現在正在使用的查詢的問題編輯。謝謝! – weltschmerz 2012-07-21 16:01:08

0

如果你正在做一次刪除重複的項目,我不會打擾編寫一個PHP腳本 - 它在sql中更清潔。

去除重複,我覺得作品最好的是一般的算法:
1.複製表
2.截斷原始表
3.設置爲準列必須是唯一的唯一索引
4.採用任何INSERT IGNORE INTO original_table SELECT * FROM duplicate_tableREPLACE INTO original_table SELECT * FROM duplicate table
5.固定鏈接表重新插入行 - 刪除孤立行(DELETE x FROM x LEFT JOIN original TABLE ON (...) WHERE original_table.id IS NULL