关于如何在数据库中查找重复项有很多问题,但不是我遇到的具体问题。
我有一张大约一张桌子。 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
它完美地显示原件和副本,但我需要摆脱原件,即与相关数据一起找到的第一个原件。我怎么能做到这一点?
答案 0 :(得分:2)
你可以JOIN
将表格放到自己身上并在SQL中完成所有操作(我知道你说你不认为可以,但如果是这样的话,我会感到惊讶)。您需要做的就是将用于测试重复项的所有列放入ON
的{{1}}子句中。
JOIN
这将只返回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
重复的行的col1
个。您可以将所需的任何字符串比较合并到此中,col2
子句可以像您需要的那样复杂。例如:
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
列相同的行,因此只能查找重复项而不是原始的“好”记录 - 假设{{1 }是数字,“好”记录将是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
语句中不需要DELETE b.*
FROM host_webs a
INNER JOIN host_webs b ON b.web = a.web AND b.host_id > a.host_id
,因为如果您尝试在单个语句中多次删除同一行并不重要。
答案 1 :(得分:0)
如果你一次性删除重复的项目,我就不会去编写一个php脚本了 - 在sql中这样做更干净。
我发现删除重复项的一般算法效果最好:
1.复制表
2.截断原始表
3.在需要唯一的列上设置唯一索引
4.使用INSERT IGNORE INTO original_table SELECT * FROM duplicate_table
或REPLACE INTO original_table SELECT * FROM duplicate table
重新插入行
5.修复链接表 - 删除孤立行(DELETE x FROM x LEFT JOIN original TABLE ON (...) WHERE original_table.id IS NULL
)