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

テーブルをそれ自体で作成し、すべて SQL で実行できますJOIN(できないと言っているのは知っていますが、その場合は驚くでしょう)。必要なのは、重複のテストに使用するすべての列ONJOIN.

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している行ののみを返します。必要な文字列比較をこれに組み込むことができます。句は必要に応じて複雑にすることができます。例えば: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

1つのステートメントで同じ行を複数回削除しようとしても問題にならないためGROUP BY、ステートメントでは は必要ありません。DELETE

于 2012-07-12T22:34:17.283 に答える
0

重複するアイテムを 1 回だけ削除する場合は、わざわざ php スクリプトを作成する必要はありません。SQL で行う方がクリーンです。


1. テーブルを複製する
2. 元のテーブルを切り捨てる3.
一意にする必要がある列に一意のインデックスを設定する4.または
いずれかを使用して行を再挿入する 5. 固定リンクテーブル - 孤立した行を削除 ( )INSERT IGNORE INTO original_table SELECT * FROM duplicate_tableREPLACE INTO original_table SELECT * FROM duplicate table
DELETE x FROM x LEFT JOIN original TABLE ON (...) WHERE original_table.id IS NULL

于 2012-07-12T22:34:04.567 に答える