5

我们有一个 SQL Server 表,其中包含公司名称、地址和联系人姓名(等等)。

我们会定期收到来自外部来源的数据文件,这些文件需要我们与此表进行匹配。不幸的是,数据略有不同,因为它来自完全不同的系统。例如,我们有“123 E. Main St.”。我们收到“123 East Main Street”。另一个例子,我们有“Acme, LLC”,文件包含“Acme Inc.”。另一个是,我们有“Ed Smith”,他们有“Edward Smith”

我们有一个遗留系统,它利用一些相当复杂和 CPU 密集型的方法来处理这些匹配。有些涉及纯 SQL,有些涉及 Access 数据库中的 VBA 代码。当前系统好但不完善,繁琐难维护

这里的管理层希望扩大其用途。将继承系统支持的开发人员希望将其替换为需要更少维护的更敏捷的解决方案。

是否有一种普遍接受的方式来处理这种数据匹配?

4

5 回答 5

4

这是我为几乎相同的堆栈编写的内容(我们需要标准化硬件的制造商名称,并且存在各种变体)。虽然这是客户端(确切地说是 VB.Net)——并使用 Levenshtein 距离算法(为获得更好的结果而修改):

    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
于 2008-09-24T12:44:55.677 回答
2

SSIS(在 Sql 2005+ Enterprise 中)具有Fuzzy Lookup,专为此类数据清理问题而设计。

除此之外,我只知道特定领域的解决方案——例如地址清理或通用字符串匹配技术

于 2008-09-24T12:49:18.363 回答
2

有许多供应商提供产品来进行这种模式匹配。我会做一些研究,找到一个好的、有声望的产品,然后废弃国产系统

正如您所说,您的产品只是好的,这对于企业来说是一种足够普遍的需求,我敢肯定那里有不止一种优秀的产品。即使许可证花费几千美元,它仍然比支付一堆开发人员在内部工作要便宜。

此外,“复杂”、“CPU 密集型”、“VBA 代码”和“Access 数据库”这些短语同时出现在系统描述中,这也是寻找优秀第三方工具的另一个原因。

编辑:.NET 也有可能有一个内置组件来做这种事情,在这种情况下,您不必为此付费。.NET 提供的工具时常让我感到惊讶。

于 2008-09-24T12:54:11.597 回答
1

Access 并没有真正的工具。在理想的世界中,我会选择 SSIS 解决方案并使用模糊查找。但是,如果您当前正在使用 Access,那么您的办公室购买 SQL Server 企业版的机会对我来说似乎很低。如果您受困于当前环境,则可以尝试蛮力方法。

从标准化的地址清理开始。选择 Street、raod 等的标准缩写,并编写代码以更改这些标准地址的所有正常变化。用一个空格替换任何两个空格的实例,修剪所有数据并删除所有非字母数字字符。如您所见,这是一项艰巨的任务。

至于公司名称,也许您可​​以尝试匹配名称的前 5 个字符和地址或电话。您还可以创建一个包含已知变体的表以及它们在您的数据库中与您的数据库相关的内容,以用于清理未来的文件。因此,如果您使用 id 100 is Acme, Inc. 进行记录,您可能会有这样的表格:

idfield 名称

100 Acme, Inc.

100 Acme, Inc

100 Acme, Incorporated

100 Acme, LLC

100 顶点

如果您每次找到并修复重复项(使其成为去重复过程的一部分)并且如果您每次都能够匹配的第一部分都进行条目,那么这将开始很小但随着时间的推移而建立现有公司的名称和地址。

我还会查看 Torial 发布的那个功能,看看它是否有帮助。

所有这些都是痛苦和耗时的,但随着时间的推移,随着您发现新的变体并将它们添加到代码或列表中,它们会变得更好。如果您决定标准化您的地址数据,请确保首先清理生产数据,然后对工作表进行任何导入并清理它,然后尝试匹配生产数据并插入新记录。

于 2008-09-24T13:51:31.007 回答
0

有很多方法可以解决这个问题,但可能并不明显。最好的办法是找到唯一标识符,您可以使用这些标识符在字段之外匹配拼写错误等。

一些想法

  1. 显而易见的,社会安全号码,驾驶执照等
  2. 电子邮件地址
  3. 清理后的电话号码(R删除标点符号等)

就供应商而言,我刚刚回答了一个类似的问题,并粘贴在下面。

每个主要供应商都有自己的解决方案。Oracle、IBM、SAS Dataflux 等都声称在这类问题上做得最好。

独立验证评估:

澳大利亚科廷大学数据链接中心进行了一项研究,模拟了 440 万条记录的匹配。确定提供商的准确性(找到的匹配数与可用的匹配数。错误匹配数)

DataMatch Enterprise,最高精度 (>95%),非常快速,低成本

IBM Quality Stage,高精度 (>90%),非常快,高成本 (>$100K)

SAS 数据通量,中等准确度 (>85%),快速,高成本 (>100K) 这是我们能找到的最好的独立评估,非常彻底。

于 2013-09-12T14:01:03.720 回答