Domanda
Abbiamo una tabella di SQL Server che contiene il nome dell'azienda, l'indirizzo e il nome del contatto (tra gli altri).
Riceviamo regolarmente file di dati da fonti esterne che ci richiedono di confrontarci con questa tabella. Sfortunatamente, i dati sono leggermente diversi poiché provengono da un sistema completamente diverso. Ad esempio, abbiamo " 123 E. Main St. " e riceviamo "123 East Main Street". Un altro esempio, abbiamo " Acme, LLC " e il file contiene " Acme Inc. " ;. Un altro è che abbiamo & Ed; Ed Smith " e hanno " Edward Smith "
Abbiamo un sistema legacy che utilizza alcuni metodi piuttosto complessi e ad alta intensità di CPU per gestire queste partite. Alcuni coinvolgono SQL puro e altri riguardano il codice VBA in un database di Access. L'attuale sistema è buono ma non perfetto, ingombrante e difficile da mantenere
La direzione qui vuole espandere il suo utilizzo. Gli sviluppatori che erediteranno il supporto del sistema vogliono sostituirlo con una soluzione più agile che richiede meno manutenzione.
Esiste un modo comunemente accettato per gestire questo tipo di corrispondenza dei dati?
Soluzione
Ecco qualcosa che ho scritto per uno stack quasi identico (dovevamo standardizzare i nomi dei produttori per l'hardware e c'erano molte varianti). Questo è lato client (VB.Net per essere esatti) - e usa l'algoritmo di distanza Levenshtein (modificato per risultati migliori):
Public Shared Function FindMostSimilarString(ByVal toFind As String, ByVal ParamArray stringList() As String) As String
Dim bestMatch As String = ""
Dim bestDistance As Integer = 1000 'Almost anything should be better than that!
For Each matchCandidate As String In stringList
Dim candidateDistance As Integer = LevenshteinDistance(toFind, matchCandidate)
If candidateDistance < bestDistance Then
bestMatch = matchCandidate
bestDistance = candidateDistance
End If
Next
Return bestMatch
End Function
'This will be used to determine how similar strings are. Modified from the link below...
'Fxn from: http://ca0v.terapad.com/index.cfm?fa=contentNews.newsDetails&newsID=37030&from=list
Public Shared Function LevenshteinDistance(ByVal s As String, ByVal t As String) As Integer
Dim sLength As Integer = s.Length ' length of s
Dim tLength As Integer = t.Length ' length of t
Dim lvCost As Integer ' cost
Dim lvDistance As Integer = 0
Dim zeroCostCount As Integer = 0
Try
' Step 1
If tLength = 0 Then
Return sLength
ElseIf sLength = 0 Then
Return tLength
End If
Dim lvMatrixSize As Integer = (1 + sLength) * (1 + tLength)
Dim poBuffer() As Integer = New Integer(0 To lvMatrixSize - 1) {}
' fill first row
For lvIndex As Integer = 0 To sLength
poBuffer(lvIndex) = lvIndex
Next
'fill first column
For lvIndex As Integer = 1 To tLength
poBuffer(lvIndex * (sLength + 1)) = lvIndex
Next
For lvRowIndex As Integer = 0 To sLength - 1
Dim s_i As Char = s(lvRowIndex)
For lvColIndex As Integer = 0 To tLength - 1
If s_i = t(lvColIndex) Then
lvCost = 0
zeroCostCount += 1
Else
lvCost = 1
End If
' Step 6
Dim lvTopLeftIndex As Integer = lvColIndex * (sLength + 1) + lvRowIndex
Dim lvTopLeft As Integer = poBuffer(lvTopLeftIndex)
Dim lvTop As Integer = poBuffer(lvTopLeftIndex + 1)
Dim lvLeft As Integer = poBuffer(lvTopLeftIndex + (sLength + 1))
lvDistance = Math.Min(lvTopLeft + lvCost, Math.Min(lvLeft, lvTop) + 1)
poBuffer(lvTopLeftIndex + sLength + 2) = lvDistance
Next
Next
Catch ex As ThreadAbortException
Err.Clear()
Catch ex As Exception
WriteDebugMessage(Application.StartupPath , [Assembly].GetExecutingAssembly().GetName.Name.ToString, MethodBase.GetCurrentMethod.Name, Err)
End Try
Return lvDistance - zeroCostCount
End Function
Altri suggerimenti
SSIS (in Sql 2005+ Enterprise) ha Ricerca fuzzy che è progettato proprio per tali problemi di pulizia dei dati.
A parte questo, conosco solo soluzioni specifiche del dominio, come address cleaning o tecniche di corrispondenza delle stringhe .
Ci sono molti venditori là fuori che offrono prodotti per fare questo tipo di corrispondenza dei modelli. Farei qualche ricerca e troverei un prodotto valido e rinomato e eliminerei il sistema coltivato in casa .
Come dici tu, il tuo prodotto è solo buono, e questo è un bisogno abbastanza comune per le aziende che sono sicuro che ci sia più di un prodotto eccellente là fuori. Anche se per una licenza costa qualche migliaio di dollari, sarà comunque più economico che pagare un mucchio di sviluppatori per lavorare su qualcosa internamente.
Inoltre, il fatto che le frasi "intricate", "ad alta intensità di CPU", "codice VBA" e " Accedi al database " apparire insieme nella descrizione del sistema è un altro motivo per trovare un buon strumento di terze parti.
EDIT: è anche possibile che .NET abbia un componente integrato che fa questo tipo di cose, nel qual caso non dovresti pagarlo. Ogni tanto mi sorprendono ancora gli strumenti offerti da .NET.
Sto affrontando esattamente lo stesso problema. Dai un'occhiata a:
Strumenti per la corrispondenza dei dati di nome / indirizzo
per alcuni strumenti che potrebbero essere utili.
L'accesso non ha davvero gli strumenti per questo. In un mondo ideale andrei con la soluzione SSIS e userei la ricerca fuzzy. Ma se stai utilizzando Access, le possibilità che il tuo ufficio acquisti SQL Server Enterprise Edition mi sembrano basse. Se sei bloccato con l'ambiente attuale, potresti provare un approccio a forza bruta.
Inizia con la pulizia standardizzata degli indirizzi. Abbraccia abbreviazioni standard per Street, raod, ecc. E scrivi il codice per modificare tutte le normali variazioni di quelle aggiunte standard. Sostituisci qualsiasi istanza di due spazi con uno spazio, ritaglia tutti i dati e rimuovi tutti i caratteri non alfanumerici. Come puoi vedere, questo è piuttosto un compito.
Per quanto riguarda i nomi delle società, forse puoi provare ad abbinare i primi 5 caratteri del nome e l'indirizzo o il telefono. È inoltre possibile creare una tabella con le varianti note e le relative relazioni nel database da utilizzare per la pulizia dei file futuri. Quindi, se registri con ID 100 è Acme, Inc., potresti avere una tabella come questa:
Nome idfield
100 Acme, Inc.
100 Acme, Inc
100 Acme, Incorporated
100 Acme, LLC
100 Acme
Questo inizierà in piccolo ma si accumulerà nel tempo se si inserisce una voce ogni volta che si trova e si corregge un duplicato (si inserisce nel processo di rimozione del supporto) e se si immette una voce ogni volta che si è in grado di abbinare il primo parte del nome e dell'indirizzo di un'azienda esistente.
Guarderei anche quella funzione che Torial ha pubblicato e vedere se aiuta.
Tutto ciò sarebbe doloroso e dispendioso in termini di tempo, ma migliorerebbe nel tempo quando trovi nuove varianti e le aggiungi al codice o all'elenco. Se decidi di stardardizzare i tuoi dati di indirizzo, assicurati di pulire prima i dati di produzione, quindi esegui qualsiasi importazione in una tabella di lavoro e puliscili, quindi prova a far corrispondere i dati di produzione e inserisci nuovi record.
Ho appena trovato questo link correlato.
Giuro di aver guardato prima di pubblicare questo.
Esistono diversi modi per affrontare ciò che potrebbe non essere ovvio. La cosa migliore è trovare identificatori univoci che è possibile utilizzare per la corrispondenza all'esterno dei campi con errori di ortografia, ecc.
Alcuni pensieri
- L'ovvio numero di previdenza sociale, patente di guida, ecc.
- Indirizzo email
- Numero di telefono pulito (Rimuovi punteggiatura, ecc.)
Per quanto riguarda i venditori, ho appena risposto a una domanda simile e sto incollando di seguito.
Ogni fornitore principale ha la propria soluzione. Oracle, IBM, SAS Dataflux, ecc. E ciascuno afferma di essere il migliore in questo tipo di problema.
Valutazione verificata indipendente:
È stato condotto uno studio presso il Curtin University Center for Data Linkage in Australia che simula la corrispondenza di 4,4 milioni di record. Identificato quali provider avevano in termini di precisione (Numero di corrispondenze trovate vs disponibili. Numero di corrispondenze false)
DataMatch Enterprise, massima precisione (> 95%), molto veloce, basso costo
IBM Quality Stage , alta precisione (> 90%), molto veloce, alto costo (> $ 100K)
Flusso di dati SAS, precisione media (> 85%), veloce, costo elevato (> 100K) Questa è stata la migliore valutazione indipendente che siamo riusciti a trovare, è stata molto approfondita.