2016-07-13 11 views
1

私は、mysqlから重複を削除することがよくあることをよく知っています。しかし、私の場合は解決策のどれもうまくいきません。大規模なmysqlアドレスデータベースから重複を削除

だから、私はほとんどこのようなアドレスデータとDBを持っている:

ID; Anrede; Vorname; Nachname; Strasse; Hausnummer; PLZ; Ort; Nummer_Art; Vorwahl; Rufnummer 

IDは、主キー、ユニークです。

、私はこのような例entrysている:彼らは私のため関連がないので、

1;Herr;Michael;Müller;Testweg;1;55555;Testhausen;Mobile;;67890 
2;Herr;Michael;Müller;Testweg;1;55555;Testhausen;Fixed;045678;877656 

異なるのPhoneNumberは、問題ではありません。だから私は姓、ストリート、および郵便番号の重複を削除したいです。その場合、ID 1またはID 2。両方のどちらが重要でないか。

私は実際に削除して、このようにそれを試してみました:完全なテーブルが10Mio行の上に含まれてい

INSERT INTO Import_Daten_1 

SELECT MIN(db.id), 
     db.Anrede, 
     db.Firstname, 
     db.Lastname, 
     db.Branche, 
     db.Strasse, 
     db.Hausnummer, 
     db.Ortsteil, 
     db.Land, 
     db.PLZ, 
     db.Ort, 
     db.Kontaktart, 
     db.Vorwahl, 
     db.Durchwahl 

FROM Import_Daten db, 
     Import_Daten dbl 

WHERE db.lastname = dbl.lastname AND 
     db.Strasse = dbl.Strasse And 
     db.PLZ = dbl.PLZ; 

DELETE db 

FROM Import_Daten db, 
    Import_Daten dbl 

WHERE db.id > dbl.id AND 
     db.Lastname = dbl.Lastname AND 
     db.Strasse = dbl.Strasse AND 
     db.PLZ = dbl.PLZ; 

、コピーテーブルに挿入します。サイズは実際に私の問題です。 mysqlは、1,5GHZと4GBのRAMを搭載したMacBook上のMAMPサーバー上で動作します。それほど速くない。 SQL文はphpmyadminで実行されます。実際に私は他のシステムの可能性がありません。

答えて

0

たとえば、新しい列を追加できます。 uqとし、UNIQUEとします。

ALTER TABLE Import_Daten 
ADD COLUMN `uq` BINARY(16) NULL, 
ADD UNIQUE INDEX `uq_UNIQUE` (`uq` ASC); 

これが行われると、すべてのエントリが更新され、クエリを再度実行すると、すべての重複が値でuqフィールドを持つことになります。この

UPDATE IGNORE Import_Daten 
SET 
    uq = UNHEX(
      MD5(
      CONCAT(
       Import_Daten.Lastname, 
       Import_Daten.Street, 
       Import_Daten.Zipcode 
      ) 
      ) 
     ) 
WHERE 
    uq IS NULL; 

ようUPDATEクエリを実行することができます= NULL除去することができる。

結果は次のようになります。新しく追加された行は常にuqハッシュを作成して、一度すべてのエントリが一意である主キーとしてこれを使用することを検討して

0 row(s) affected, 1 warning(s): 1062 Duplicate entry...

について。

+0

Phantastic!本当に早く働いていた!どうもありがとう! – swapfile

+0

重複の挿入を防止するために、(Lastname、Strasse、PLZ)フィールドの一意索引を追加できます。 – olegsv

+0

このソリューションを初めて適用すると、すべての重複レコードが削除されます。重複した記録を1部も残さない。 – olegsv

1

stored procedureと書くと、別のデータを選択するたびに(たとえば、2つの値の間でrownumber)、その範囲からのみ削除できます。この方法でゆっくりビットを削除して複製を削除します

+0

ありがとう。私はストアドプロシージャの経験がありません。私はこれを見ていきます。しかし、jが行番号内の範囲を「クリーン」にして、データがソートされていない場合、それは機能しませんか? – swapfile

+0

@Chrisko - いくつかのドキュメントへのリンクを追加しました –

1

より効果的な2つのテーブルソリューションは次のようになります。 本当に削除する必要のあるデータのみを保存することができ、重複した情報を含むフィールドだけを保存することができます。 Lastname、Branche、Haushummerフィールドで重複データを探しているとしましょう。

重複データ

DROP TABLE data_to_delete;

は、我々は(私はすべてのフィールドがVARCHAR(255)タイプ持っていると仮定)を削除するために必要なデータを持つテーブルを移入保持するテーブルを作成します

CREATE TABLE data_to_delete ( id BIGINT COMMENT 'this field will contain ID of row that we will not delete', cnt INT, Lastname VARCHAR(255), Branche VARCHAR(255), Hausnummer VARCHAR(255) ) AS SELECT min(t1.id) AS id, count(*) AS cnt, t1.Lastname, t1.Branche, t1.Hausnummer FROM Import_Daten AS t1 GROUP BY t1.Lastname, t1.Branche, t1.Hausnummer HAVING count(*)>1 ;

次に、重複したデータを削除し、すべての重複セットのレコードを1つだけ残しましょう。

DELETE Import_Daten FROM Import_Daten LEFT JOIN data_to_delete ON Import_Daten.Lastname=data_to_delete.Lastname AND Import_Daten.Branche=data_to_delete.Branche AND Import_Daten.Hausnummer = data_to_delete.Hausnummer WHERE Import_Daten.id != data_to_delete.id;

DROP TABLE data_to_delete;

+0

ありがとうございます。それも動作します。しかしBernhardからのバージョンは、より高速で、より多くのインポートのためのより良いです。 – swapfile

+0

@Chrisko私はそれがより速いことに同意します。重複したレコードの挿入を防ぐために、一意のインデックスを使用できます。さらに、既存のデータにこのソリューションを適用するのは恐れがあります。重複したレコードはすべて削除され、重複シリーズのコピーは1つも残されません。 – olegsv

関連する問題