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

它完美地显示了原件和副本,但我需要摆脱原件,即与相关数据一起找到的第一个。我怎样才能做到这一点?

4

2 回答 2

2

您可以JOIN将表放在自身上并在 SQL 中完成所有操作(我知道您说您认为您不能,但如果是这种情况,我会感到惊讶)。您需要做的就是将用于测试重复项的所有列ON放入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的行的 s 。您可以将所需的任何字符串比较合并到其中,该子句可以根据需要变得复杂。例如:col1col2ON

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

我想这里的最终游戏将是删除重复项,因此,如果您有勇气,实际上可以一口气删除它们:

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

The GROUP BY is not necessary in the DELETE statement because it doesn't matter if you try and delete the same row more than once in a single statement.

于 2012-07-12T22:34:17.283 回答
0

如果您要 1 次删除重复项,我不会费心编写 php 脚本 - 在 sql 中执行此操作会更干净。

我认为最有效的删除重复项的一般算法是:
1. 复制表
2. 截断原始表
3. 在需要唯一的列上设置唯一索引
4. 使用INSERT IGNORE INTO original_table SELECT * FROM duplicate_tableOR重新插入行REPLACE INTO original_table SELECT * FROM duplicate table
5. 固定链接表格 - 删除孤立的行 ( DELETE x FROM x LEFT JOIN original TABLE ON (...) WHERE original_table.id IS NULL)

于 2012-07-12T22:34:04.567 回答