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?

È stato utile?

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

  1. L'ovvio numero di previdenza sociale, patente di guida, ecc.
  2. Indirizzo email
  3. 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top