Pregunta

Tenemos una tabla de SQL Server que contiene el nombre de la empresa, la dirección y el nombre del contacto (entre otros).

Regularmente recibimos archivos de datos de fuentes externas que requieren que los comparemos con esta tabla.Desafortunadamente, los datos son ligeramente diferentes ya que provienen de un sistema completamente diferente.Por ejemplo, tenemos "123 E.Main St." y recibimos "123 East Main Street".Otro ejemplo, tenemos "Acme, LLC" y el archivo contiene "Acme Inc."Otra es que tenemos "Ed Smith" y ellos tienen "Edward Smith".

Tenemos un sistema heredado que utiliza algunos métodos bastante complejos y que requieren un uso intensivo de la CPU para manejar estas coincidencias.Algunos implican SQL puro y otros implican código VBA en una base de datos de Access.El sistema actual es bueno pero no perfecto y es engorroso y difícil de mantener.

La dirección aquí quiere ampliar su uso.Los desarrolladores que heredarán el soporte del sistema quieren sustituirlo por una solución más ágil y que requiera menos mantenimiento.

¿Existe una forma comúnmente aceptada de abordar este tipo de coincidencia de datos?

¿Fue útil?

Solución

Aquí hay algo que escribí para una pila casi idéntica (necesitábamos estandarizar los nombres de los fabricantes para el hardware y hubo todo tipo de variaciones).Sin embargo, este es el lado del cliente (VB.Net para ser exactos), y utiliza el algoritmo de distancia de Levenshtein (modificado para obtener mejores resultados):

    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

Otros consejos

SSIS (en Sql 2005+ Enterprise) tiene Búsqueda difusa que está diseñado precisamente para estos problemas de limpieza de datos.

Aparte de eso, sólo conozco soluciones específicas de dominio, como limpieza de direcciones, o generales técnicas de coincidencia de cadenas.

Hay muchos proveedores que ofrecen productos para realizar este tipo de coincidencia de patrones.Investigaría un poco y encontrar un producto bueno y de buena reputación y desechar el sistema local.

Como usted dice, su producto solo es bueno y esta es una necesidad bastante común para las empresas, por lo que estoy seguro de que existe más de un producto excelente.Incluso si una licencia cuesta unos miles de dólares, seguirá siendo más barato que pagar a un grupo de desarrolladores para que trabajen en algo internamente.

Además, el hecho de que las frases "complejo", "CPU intensivo", "código VBA" y "Base de datos de acceso" aparezcan juntas en la descripción de su sistema es otra razón para buscar una buena herramienta de terceros.

EDITAR:También es posible que .NET tenga un componente incorporado que haga este tipo de cosas, en cuyo caso no tendría que pagar por ello.Todavía me sorprenden de vez en cuando las herramientas que ofrece .NET.

Estoy lidiando con exactamente el mismo problema.Echa un vistazo a:

Herramientas para hacer coincidir datos de nombre/dirección

para algunas herramientas que podrían ayudar.

Access realmente no tiene las herramientas para esto.En un mundo ideal, optaría por la solución SSIS y utilizaría la búsqueda difusa.Pero si actualmente utiliza Access, las posibilidades de que su oficina compre la edición SQL Server Enterprise me parecen bajas.Si está atrapado en el entorno actual, podría intentar un enfoque de fuerza bruta.

Comience con una limpieza estandarizada de direcciones.Elija abreviaturas estándar para Street, raod, etc.y escribir código para cambiar todas las variaciones normales a esas direcciones estándar.Reemplace cualquier instancia de dos espacios con un espacio, recorte todos los datos y elimine los caracteres no alfanuméricos.Como puedes ver, esto es toda una tarea.

En cuanto a los nombres de empresas, tal vez puedas intentar hacer coincidir los primeros 5 caracteres del nombre y la dirección o el teléfono.También puede crear una tabla de variaciones conocidas y con qué se relacionarán en su base de datos para usarla en la limpieza de archivos futuros.Entonces, si graba con id 100 es Acme, Inc.podrías tener una tabla como esta:

Nombre del campo de identificación

100 Acme, Inc.

100 Acme, Inc.

100 Acme, incorporada

100 Acme, LLC

100 cima

Esto comenzará poco a poco, pero se desarrollará con el tiempo si realiza una entrada cada vez que encuentre y corrija un duplicado (hágalo parte de su proceso de eliminación de duplicaciones) y si realiza una entrada cada vez que pueda hacer coincidir la primera parte del nombre y dirección a una empresa existente.

También miraría la función publicada por Torial y vería si ayuda.

Todo esto sería doloroso y consumiría mucho tiempo, pero mejoraría con el tiempo a medida que encuentre nuevas variaciones y las agregue al código o lista.Si decide estandarizar sus datos de dirección, asegúrese de limpiar primero los datos de producción, luego realice cualquier importación a una mesa de trabajo y límpiela, luego intente hacer coincidir los datos de producción e insertar nuevos registros.

acabo de encontrar esto enlace eso está relacionado.

Juro que miré antes de publicar esto.

Hay bastantes maneras de abordar esto que pueden no ser obvias.Lo mejor es encontrar identificadores únicos que pueda usar para hacer coincidir fuera de los campos con errores ortográficos, etc.

Algunos pensamientos

  1. Lo obvio: número de seguro social, licencia de conducir, etc.
  2. Dirección de correo electrónico
  3. Número de teléfono limpio (eliminar puntuación, etc.)

En lo que respecta a los proveedores, acabo de responder una pregunta similar y la pego a continuación.

Cada proveedor importante tiene su propia solución.Oracle, IBM, SAS Dataflux, etc. y cada uno afirma ser el mejor en este tipo de problemas.

Evaluación verificada independiente:

Hubo un estudio realizado en el Centro de Enlace de Datos de la Universidad de Curtin en Australia que simuló la coincidencia de 4,4 millones de registros.Identificó lo que tenían los proveedores en términos de precisión (número de coincidencias encontradas versus disponibles).Número de coincidencias falsas)

empresa de coincidencia de datos, Máxima precisión (>95%), muy rápido y bajo coste

Etapa de calidad de IBM , alta precisión (>90 %), muy rápido, alto costo (>$100 000)

Flujo de datos SAS, precisión media (> 85%), rápido, alto costo (> 100k) que fue la mejor evaluación independiente que pudimos encontrar, fue muy exhaustiva.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top