2016-12-22 2 views
2

Hintergrund - Ich habe eine Reihe von Kundendaten und verwendet einen String-Matching-Algorithmus, um alle Datensätze auf Ähnlichkeit zu vergleichen. Ich muss dann die Ergebnisse, die sich entweder direkt oder durch Assoziation miteinander verbinden, gruppieren und eine eindeutige ID für jede Gruppe anwenden.SQL Server Record Linkage nach String-Matching

Problem - ich kann nicht einen Weg finden Datensätze miteinander zu verknüpfen und eine eindeutige ID für jede Gruppe

Beispiel

Daten sieht derzeit wie folgt für die Spiele anzuwenden, die gefunden wurden, (MatchScore ist hier nicht relevant für das Problem, sondern um zu zeigen, woher die Daten stammen).

+-------------+-------------+------------+ 
| CustomerID1 | CustomerID2 | MatchScore | 
+-------------+-------------+------------+ 
|  2021000 |  2707799 | 0.075  | 
|  2021000 |  3856308 | 0.082  | 
|  774062 |  774063 | 0.041  | 
|  998328 |  2278386 | 0.063  | 
|  998328 |  998329 | 0.058  | 
|  998329 |  2278386 | 0.030  | 
+-------------+-------------+------------+ 

Die unteren 3 Datensätze sind alle verknüpft, daher möchte ich ihnen die gleiche ID zugeordnet haben.

visual image of these records all being related

Dies ist, was ich die Daten wie

+----+-------------+-------------+------------+ 
| ID | CustomerID1 | CustomerID2 | MatchScore | 
+----+-------------+-------------+------------+ 
| 1 |  998328 |  2278386 | 0.063  | 
| 1 |  998328 |  998329 | 0.058  | 
| 1 |  998329 |  2278386 | 0.030  | 
| 2 |  2021000 |  2707799 | 0.075  | 
| 2 |  2021000 |  3856308 | 0.082  | 
| 3 |  774062 |  774063 | 0.041  | 
+----+-------------+-------------+------------+ 

oder ähnlich

+----+------------+ 
| ID | CustomerID | 
+----+------------+ 
| 1 | 2278386 | 
| 1 |  998328 | 
| 1 |  998329 | 
| 2 | 2021000 | 
| 2 | 2707799 | 
| 2 | 3856308 | 
| 3 |  774062 | 
| 3 |  774063 | 
+----+------------+ 

Code aussehen soll der Beispieltabelle

select '998328' as CustomerID1,'998329' as CustomerID2,'0.058' as MatchScore 
into #tmp 
union 
select '998328' as CustomerID1,'2278386' as CustomerID2,'0.063' as MatchScore 
union 
select '998329' as CustomerID1,'2278386' as CustomerID2,'0.030' as MatchScore 
union 
select '2021000' as CustomerID1,'2707799' as CustomerID2,'0.075' as MatchScore 
union 
select '2021000' as CustomerID1,'3856308' as CustomerID2,'0.082' as MatchScore 
union 
select '774062' as CustomerID1,'774063' as CustomerID2,'0.041' as MatchScore 

select * from #tmp 

erzeugen Wie ich sage, kann ich nicht denken, wie man die Aufzeichnungen verbindet, ich habe alle Arten von Verbindungen versucht, aber der Eureka-Moment kommt nie. Bitte kannst du helfen.

Dank

+3

Was meinen Sie mit den unteren 3 Datensätzen? Sind sie nur verknüpft, weil "CustomerID1" mit mehreren "CustomerId2" -Werten aufgelistet ist? Und warum haben 'CustomerID1' 998328 und 998329 denselben ID-Wert? – Taryn

+0

ist, weil die 3 separaten Datensätze bedeuten, dass die Kunden 998328 und 2278386 übereinstimmen, 998328 und 998329 übereinstimmen, 998329 und 2278386 übereinstimmen. Daher wurde gezeigt, dass alle 3 übereinstimmen, also erhalten Sie die gleiche ID. – DataPro

Antwort

1

Ich bin nicht sicher, ob dies das Ergebnis Sie erwarten,

with tmp as(
select '998328' as CustomerID1,'998329' as CustomerID2,'0.058' as MatchScore 
union 
select '998328' as CustomerID1,'2278386' as CustomerID2,'0.063' as MatchScore 
union 
select '998329' as CustomerID1,'2278386' as CustomerID2,'0.030' as MatchScore 
union 
select '2021000' as CustomerID1,'2707799' as CustomerID2,'0.075' as MatchScore 
union 
select '2021000' as CustomerID1,'3856308' as CustomerID2,'0.082' as MatchScore 
union 
select '774062' as CustomerID1,'774063' as CustomerID2,'0.041' as MatchScore 
union 
select '774063' as CustomerID1,'774062' as CustomerID2,'0.041' as MatchScore 
union 
select '774063' as CustomerID1,'774063' as CustomerID2,'0.041' as MatchScore) 


select DENSE_RANK() OVER(ORDER BY rank_value) id, t1.CustomerID1, t1.CustomerID2 
from(
    select 
     t1.*, 
     case 
      when t2.CustomerID1 IS NOT NULL 
       THEN t2.CustomerID1 
      ELSE t3.CustomerID1 
     end rank_value 

    from tmp t1 
    left join tmp t2 
    on (t1.CustomerID1 = t2.CustomerID2 
      and t1.CustomerID2!=t2.CustomerID1 
      and (t1.CustomerID1 != t1.CustomerID2 and t2.CustomerID1 != t2.CustomerID2)) 
     or (t1.CustomerID1 = t2.CustomerID1 
      and t1.CustomerID2 != t2.CustomerID2 
      and (t1.CustomerID1 != t1.CustomerID2)) 
    left join tmp t3 
     on t1.CustomerID1 = t3.CustomerID2 
      and t1.CustomerID2=t3.CustomerID1 
)t1 

Ich bin das unten stehende Ergebnis

enter image description here

Hinweis bekommen: DENSE_RANK() Funktion verfügbar ist ab Version 2012

+0

Netter Ansatz, aber ich denke, es ist ein kleiner Buggy: Wenn Sie einen weiteren Datensatz zu Ihrem tmp hinzufügen, wählen Sie 774063 als CustomerID1, 774062 als CustomerID2, 0,041 als MatchScore oder 774063 als ID1 und ID2. die IDs sind durcheinander ... – Tyron78

+0

Was Tyron78 ​​sagte, stimmt, dieser Ansatz funktioniert in diesem Beispiel, aber eine kleine Änderung in den Daten führt zu falschen Ergebnissen. Ich bin nicht davon überzeugt, dass es einen schönen Set-basierten Ansatz gibt, aber wenn ich einen finde, werde ich es hier zurück posten – DataPro

+0

@ Tyron78 ​​Das ist wirklich ein guter Fang. Ich habe meine Antwort entsprechend geändert, um es zu erreichen. – Viki888