Comparación de datos
-
02-07-2019 - |
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?
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
- Lo obvio: número de seguro social, licencia de conducir, etc.
- Dirección de correo electrónico
- 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.