2010-02-09 20 views
25

Ich habe ein paar Lösungen dafür gesehen, aber ich frage mich, was der beste und effizienteste Weg ist, einen Tisch zu entdupsen. Sie können Code (SQL, etc.) verwenden, um Ihren Punkt zu veranschaulichen, aber ich suche nur nach grundlegenden Algorithmen. Ich nahm an, dass es auf SO bereits eine Frage dazu geben würde, aber ich konnte keine finden, also wenn es schon existiert, gib mir einfach einen Hinweis.Was ist der beste Weg, um eine Tabelle zu deduplizieren?

(Nur um zu klären - ich beziehe mich in einer Tabelle loswerden Duplikate zu bekommen, die eine inkrementelle automatische PK hat und hat einige Zeilen, die Duplikate in alles, aber das PK-Feld sind.)

+0

Meinst du das Zusammenfallen von * identischen * Duplikaten (mit Ausnahme der PK) oder das Zusammenfalten * von hinreichend ähnlichen * Duplikaten? Ersteres kann ziemlich einfach gemacht werden, letzteres ist eine potentielle Welt der Unsicherheit und des Schmerzes. –

+0

@j_random_hacker - ich meinte völlig identisch. Siehe den Wortlaut des Beitrags - "Ich beziehe mich darauf, Duplikate loszuwerden ... Zeilen, die Duplikate in * allem außer dem PK-Feld * sind." – froadie

+0

Entschuldigung, ich habe nicht sorgfältig genug gelesen ... –

Antwort

1

Sie einen erzeugen könnten Hash für jede Zeile (ohne die PK), speichern Sie es in einer neuen Spalte (oder wenn Sie keine neuen Spalten hinzufügen können, können Sie die Tabelle in einen temporären Staging-Bereich verschieben?), und suchen Sie dann nach allen anderen Zeilen mit dem gleichen Hash. Natürlich müssten Sie sicherstellen können, dass Ihre Hash-Funktion nicht den gleichen Code für verschiedene Zeilen erzeugt.

Wenn zwei Reihen doppelte sind, ist es gleichgültig, die Sie loswerden? Ist es möglich, dass andere Daten von beiden Duplikaten abhängig sind? Wenn ja, werden Sie durch ein paar Schritte gehen müssen:

  • Die Betrogenen
  • einer von ihnen wählen als dupeA zu beseitigen
  • alle abhängigen Daten finden auf dupeA
  • Alter, dass die Daten verweisen zu dupeB
  • löschen dupeA. Dies könnte einfach oder kompliziert sein, je nach vorhandenem Datenmodell

.

Dieses ganze Szenario klingt wie eine Wartung und Redesign-Projekt. Wenn ja, viel Glück !!

+0

wie genau stellen Sie sicher, dass Hashes don Erzeuge nicht denselben Code für verschiedene Daten. Bei Verwendung von Hashes besteht immer die Möglichkeit für Duplikate. Downvote. –

+0

@EsbenP: Ich habe Zip-Strings gesehen, die als eine Art Hash für die ursprünglichen Strings verwendet wurden. Zumindest bekommst du keine Betrüger. – FrustratedWithFormsDesigner

+0

Ich ging davon aus, dass keine anderen Daten vom PK-Feld abhängig sind. Aber das ist ein interessanter Punkt - was würden Sie tun, wenn das so wäre? Das würde es viel komplizierter machen ... Irgendwelche Ideen? – froadie

0

Für SQL, können Sie die INSERT IGNORE INTO Tabelle SELECT xy FROM unkeyed_table verwenden; Für einen Algorithmus können Sie davon ausgehen, dass zu erhaltende Primärschlüssel wiederholt werden können, aber ein zu-Primärschlüssel den Inhalt der Zeile eindeutig identifiziert, als nur den Primärschlüssel zu hashen und nach Wiederholung suchen.

0

Ich denke, das sollte nicht mehr als nur die Gruppierung von allen Spalten außer der ID und die Auswahl einer Zeile aus jeder Gruppe erfordern - der Einfachheit halber nur die erste Zeile, aber das ist eigentlich egal, außer Sie haben zusätzliche Einschränkungen für die ID.

Oder anders herum, um die Zeilen loszuwerden ... einfach alle Zeilen löschen, akzeptieren Sie eine einzige aus allen Gruppen.

7

SELECT DISTINCT <insert all columns but the PK here> FROM foo. Erstellen Sie eine temporäre Tabelle mit dieser Abfrage (die Syntax variiert je nach RDBMS, aber normalerweise ist ein SELECT … INTO oder CREATE TABLE AS Muster verfügbar), blasen Sie dann die alte Tabelle weg und pumpen Sie die Daten aus der temporären Tabelle wieder hinein.

8

deduping ist selten einfach. Das liegt daran, dass die zu dedutierenden Datensätze oft geringfügig andere Werte haben als einige der Felder. Wählen Sie daher aus, welcher Datensatz beibehalten werden soll. Außerdem handelt es sich bei Dupletten oft um Personenaufzeichnungen, und es ist schwer zu erkennen, ob die beiden John Smiths zwei Personen oder eine Person sind, die dupliziert werden. Also geben Sie viel (50% oder mehr des gesamten Projekts) Ihrer Zeit aus, um zu definieren, was eine Kopie ausmacht und wie Sie mit den Unterschieden und Kinderakten umgehen.

Woher wissen Sie, welcher der richtige Wert ist? Für die weitere Deduplizierung müssen Sie alle untergeordneten Datensätze bearbeiten, die nicht verwaist sind. Was passiert, wenn Sie feststellen, dass Sie durch die Änderung der ID auf dem Kinddatensatz plötzlich gegen einen der eindeutigen Indizes oder Einschränkungen verstoßen - dies wird schließlich passieren und Ihr Prozess muss damit umgehen. Wenn Sie sich törichterweise entschieden haben, alle Ihre Einschränkungen nur in der Anwendung anzuwenden, werden Sie möglicherweise nicht einmal wissen, dass die Einschränkungen verletzt werden. Wenn Sie 10.000 Datensätze zu deduplizieren haben, gehen Sie nicht durch die Anwendung, um einzeln zu deduplizieren. Wenn sich die Einschränkung nicht in der Datenbank befindet, ist die Datenintegrität bei der Deduplizierung sehr hoch.

Eine weitere Komplikation ist, dass Duples nicht immer genau auf den Namen oder die Adresse übereinstimmen. Zum Beispiel ein Salesrep namens Joan Martin kann eine Kopie eines Verkaufsrepräsentanten Joan Martin-Jones vor allem, wenn sie die gleiche Adresse und E-Mail haben. ODER Sie könnten John oder Johnny im Namen haben. Oder die gleiche Straßenadresse außer einem Datensatz abgekürzt ST. und eine buchstabierte Straße. Im SQL-Server können Sie SSIS und Fuzzy-Gruppierung verwenden, um auch Beinahe-Übereinstimmungen zu identifizieren. Dies sind oft die häufigsten Fälle, da die Tatsache, dass es keine genauen Übereinstimmungen gab, der Grund dafür ist, dass sie überhaupt erst als Duplikate eingesetzt wurden.

Für einige Arten von Deduplizierung benötigen Sie möglicherweise eine Benutzeroberfläche, sodass die Person, die die Deduplizierung durchführt, auswählen kann, welcher der beiden Werte für ein bestimmtes Feld verwendet werden soll. Dies gilt insbesondere dann, wenn die Person, die dedupliziert wird, zwei oder mehr Rollen innehat. Es könnte sein, dass die Daten für eine bestimmte Rolle normalerweise besser sind als die Daten für eine andere Rolle. Oder es könnte sein, dass nur die Benutzer sicher wissen, welches der richtige Wert ist, oder sie müssen Leute kontaktieren, um herauszufinden, ob es sich wirklich um Duplikate oder einfach um zwei Personen mit demselben Namen handelt.

1

Für diejenigen von Ihnen, das einen schnellen und schmutzigen Ansatz bevorzugen, die Liste nur alle Spalten, die zusammen einen eindeutigen Datensatz einen eindeutigen Index mit diesen Spalten, wie so definieren und erstellen:

ALTEN IGNORE TABLE TABLE_NAME ADD UNIQUE (column1, column2

Sie können den eindeutigen Index nachher löschen.

3

Hier ist die Methode, die ich, wenn Sie können Ihre Betrogene Kriterien in eine Gruppe von Aussage und Ihre Tabelle hat eine ID Identitätsspalte für Einzigartigkeit erhalten:

delete t 
from tablename t 
inner join 
(
    select date_time, min(id) as min_id 
    from tablename 
    group by date_time 
    having count(*) > 1 
) t2 on t.date_time = t2.date_time 
where t.id > t2.min_id 

In diesem Beispiel wird die date_time ist die Gruppierungskriterien, wenn Wenn Sie mehr als eine Spalte haben, stellen Sie sicher, dass Sie allen beitreten.

+0

ich mag diesen. Ich habe es gerade ausprobiert und es funktioniert super für mich. –

+0

Fantastische Lösung! Vielen Dank! –

1

Ich nehme den von DShook und biete ein Deduplizierungsbeispiel, in dem Sie nur den Datensatz mit dem höchsten Datum behalten würden.

In diesem Beispiel sagen, ich habe 3 Datensätze alle mit dem gleichen app_id, und ich möchte nur das eine mit dem höchsten aktuellen Stand halten:

DELETE t 
FROM @USER_OUTBOX_APPS t 
INNER JOIN 
(
    SELECT 
     app_id 
     ,max(processed_date) as max_processed_date 
    FROM @USER_OUTBOX_APPS 
    GROUP BY app_id 
    HAVING count(*) > 1 
) t2 on 
    t.app_id = t2.app_id 
WHERE 
    t.processed_date < t2.max_processed_date 
0

Diese die duplizierten Werte in c1 Deduplizierung können:

select * from foo 
minus 
select f1.* from foo f1, foo f2 
where f1.c1 = f2.c1 and f1.c2 > f2.c2 
7

analytische Funktion ROW_NUMBER:

WITH CTE (col1, col2, dupcnt) 
AS 
(
SELECT col1, col2, 
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col1) AS dupcnt 
FROM Youtable 
) 
DELETE 
FROM CTE 
WHERE dupcnt > 1 
GO                 
0

hier ein Ich bin reingelaufen, im richtigen Leben.

Angenommen, Sie haben eine Tabelle mit externen/3rd-Party-Logins für Benutzer, und Sie werden zwei Benutzer zusammenführen und die Schlüsselwerte des Providers/Providers deduplizieren.

;WITH Logins AS 
    (
     SELECT [LoginId],[UserId],[Provider],[ProviderKey] 
     FROM [dbo].[UserLogin] 
     WHERE [UserId][email protected] -- is the user we're deleting 
       OR [UserId][email protected] -- is the user we're moving data to 
    ), Ranked AS 
    (
     SELECT Logins.* 
      , [Picker]=ROW_NUMBER() OVER (
         PARTITION BY [Provider],[ProviderKey] 
         ORDER BY CASE WHEN [UserId][email protected] THEN 1 ELSE 0 END) 
     FROM Logins 
    ) 
    MERGE Logins AS T 
    USING Ranked AS S 
    ON S.[LoginId]=T.[LoginID] 
    WHEN MATCHED AND S.[Picker]>1 -- duplicate Provider/ProviderKey 
       AND T.[UserID][email protected] -- safety check 
    THEN DELETE 
    WHEN MATCHED AND S.[Picker]=1 -- the only or best one 
       AND T.[UserID][email protected] 
    THEN UPDATE SET T.[UserID][email protected] 
    OUTPUT $action, DELETED.*, INSERTED.*; 
5

Hinzufügen von den eigentlichen Code hier für zukünftige Referenz

So gibt es 3 Schritte und damit 3 SQL-Anweisungen:

Schritt 1: Verschieben Sie die nicht Duplikate (eindeutige Tupel) in eine temporäre

Tisch
CREATE TABLE new_table as 
SELECT * FROM old_table WHERE 1 GROUP BY [column to remove duplicates by]; 

Schritt 2: die alte Tabelle löscht (oder umbenennen) Wir brauchen nicht mehr die Tabelle mit allen doppelten Einträgen, so fallen lassen!

DROP TABLE old_table; 

Schritt 3: new_table auf den Namen des OLD_TABLE

RENAME TABLE new_table TO old_table; 

Und natürlich umbenennen, vergessen Sie nicht, Ihren Buggy Code zu beheben Einfügen von Duplikaten zu stoppen!

0

Diese Methoden funktionieren, aber ohne eine explizite ID als PK dann bestimmen, welche Zeilen gelöscht werden, könnte ein Problem sein. Der Sprung in eine temporäre Tabelle, die aus dem Original gelöscht und wieder eingefügt wird, ohne die Duplikate, scheint die einfachste zu sein.

Verwandte Themen