2016-07-01 5 views
0

Das Finden von Duplikaten in einer Tabelle ist ziemlich einfach, aber ich suche nach einer Möglichkeit, diese Duplikate mit eindeutigen Bezeichnern zu gruppieren. Zum Beispiel -Mit Tsql, ist es möglich, Duplikate mit eindeutigen Zahlen zu markieren/gruppieren?

Tabelle -

Id Col1 Col2 Col3 
1  A  A2  B3 
2  B  A2  B3 
3  C  A22 B33 
4  D  A22 B33 

Die Ausgabe sollte -

Col2 Col3 UniqueId 
A2  B3  1 
A22 B33 2 

wird diese SQL über eine Million Zeilen ausgeführt werden. Ich frage mich, ob es möglich ist, es durch, ohne Gruppe zu tun (es sei denn Gruppe der effizienteste Weg ist, es zu tun)

+0

habe meine Antwort die Arbeit für Sie tun? –

+0

Vielen Dank. Scheint gut zu funktionieren, nachdem die Zählung (*)> 1 hinzugefügt wurde. Ich frage mich, ob es möglich ist, dies ohne Gruppe zu tun, um die Leistung zu verbessern? Diese SQL wird über eine Million Zeilen laufen. – Achilles

Antwort

1

Sie ROW_NUMBER() so etwas wie dieses

Testdaten

CREATE TABLE #TestData (ID int, Col1 varchar(1), Col2 varchar(3), Col3 varchar(3)) 
INSERT INTO #TestData (ID, Col1, Col2, Col3) 
VALUES 
(1,'A','A2','B3') 
,(2,'B','A2','B3') 
,(3,'C','A22','B33') 
,(4,'D','A22','B33') 

Abfrage verwenden können

SELECT Col2, Col3, UniqueID FROM 
    (SELECT ROW_NUMBER() 
     OVER (ORDER BY Col2, Col3) AS UniqueID, 
     Col2, Col3 
    FROM #TestData GROUP BY Col2, Col3) AS EMP 

Ergebnis

Col2 Col3 UniqueID 
A2  B3  1 
A22  B33  2 
+0

Vielen Dank.Scheint gut zu funktionieren, nachdem die Zählung (*)> 1 hinzugefügt wurde. Ich frage mich, ob es möglich ist, dies ohne Gruppe zu tun, um die Leistung zu verbessern? Diese SQL wird über eine Million Zeilen laufen. Ich werde die Frage auch mit diesem Kommentar aktualisieren. – Achilles

+0

Wenn Sie keine Gruppe bis dahin tun werden, müssen Sie sich entscheiden, bestimmte oder etwas ähnliches zu tun. Es würde mich interessieren, was besser wäre. Wie können Sie mir die Daten mitteilen, wenn Sie eine bessere Lösung finden? –

+0

Ich versuchte dies über 3-4 Millionen Zeilen, dauerte ein paar Sekunden. Habe noch nicht mit den anderen Ansätzen verglichen. – Achilles

0

Wie wäre es mit HASH? (Sehr ähnlich einer Antwort gab ich den anderen Tag)

Declare @Table table (id int,Col1 varchar(25),Col2 varchar(25),Col3 varchar(25)) 
Insert into @Table values 
(1,'A','A2','B3'), 
(2,'B','A2','B3'), 
(3,'C','A22','B33'), 
(4,'D','A22','B33') 

Select Distinct Col2,Col3,UniqueID=abs(cast(HashBytes('MD5', Col2+Col3) as int)) 
From @Table 

Returns

Col2 Col3 UniqueID 
A2  B3  768457807 
A22  B33  915487006 
+0

Danke. Ich wusste nicht, diese Hashwerte zu erstellen, interessante Herangehensweise. Das wird wohl auch eine Gruppe von Ihnen erfordern, oder? Welche Auswirkungen hat dieses Hashing auf die Leistung, wenn wir von einer Million Zeilen Daten sprechen? – Achilles

+0

@Achilles Es ist eine SQL-Inline-Funktion. Ich habe dies beim Maskieren von Kontoinformationen für 10 Tausende von Konten verwendet. Ihre Schönheit ist, dass sie konsistent ist und Sie sich nie um die Reihenfolge kümmern müssen. Zum Beispiel wird im obigen Beispiel morgen eine AA hinzugefügt, die nun in der Sequenz # 1 wäre. –

+0

@Achilles in meiner Antwort oben, entfernen DISTINCT und sehen, was Sie bekommen –

0

Nur ein weiterer Weg, um Ihr Problem zu lösen (ohne Verwendung von Distinct oder Gruppe von) durch eine Identität Spalte und die SQL Analytics-Funktion LAG, um Werte aus der vorherigen Zeile abzurufen. So funktioniert das nicht für SQL Server-Versionen unter 2012.

Leistung: Ich weiß nicht, ob das schneller sein wird. Wenn Sie den Datenfluss, die Tabellen-in/upd-Frequenzen und das Verwendungsmuster beschreiben können, können wir vielleicht andere (bessere) Alternativen messen und vergleichen und vielleicht sogar kommen.

Annahmen: Col2 + Col3 = Einmalig in Output Datentabelle. Die ID-Spalte kann in eine Identity-Spalte (oder eine PK-Spalte) in der Quellentabelle (= @Temp_Tbl unten) konvertiert werden. Und die Uniq_ID Spalte in der Ausgabe nicht über Seriell-zu-sein (wenn ja, dann nur ein kleines zwicken auf der Select Anw notwendig ist)

So funktioniert es: Der dervied Abfrageblock X erhält die vorherigen Werte für Col2 und Col3 basierend auf der Reihenfolge von Col2 und Col3, um 2 abgeleitete Spalten Col2_Prev und Col3_Prev zu erhalten. Dann verwenden wir diese Spalten, um die Duplikate zu eliminieren, indem wir sie in der where-Klausel verwenden.

DECLARE @Temp_Tbl TABLE (ID INT IDENTITY(1,1) , Col1 VARCHAR(5), Col2 VARCHAR(5),Col3 VARCHAR(5)) 

INSERT INTO @Temp_Tbl (Col1 , Col2, Col3) VALUES 
('A','A2','B3')  , 
('B','A2','B3')  , 
('C','A22','B33') , 
('D','A22','B33') , 
('E','A222','B333') , 
('F','A222','B333') , 
('B1','A2','B3') 

SELECT 
     X.ID as Uniq_ID 
     ,X.Col1 
     ,X.Col2 
     ,X.Col3 
    -- ,X.Col2_Prev -- Uncomment For Troubleshooting 
    -- ,X.Col3_Prev -- Uncomment For Troubleshooting 
FROM 
     (
      SELECT A.*  , 
        Lag(A.Col2, 1, 0) OVER (ORDER BY A.Col2,A.Col3) as Col2_Prev , -- Get Value for Col2 from Previous Row 
        Lag(A.Col3, 1, 0) OVER (ORDER BY A.Col2,A.Col3) as Col3_Prev -- Get Value for Col3 from Previous Row 
      From @Temp_Tbl A 
     ) X 
WHERE X.Col2 <> X.Col2_Prev AND 
     X.Col3 <> X.Col3_Prev 

Ergebnis:

Uniq_ID Col1 Col2 Col3 
1  A A2  B3 
3  C A22 B33 
5  E A222 B333 
+0

Sehr cool Ansatz. Danke, ich werde es ausprobieren – Achilles

Verwandte Themen