5

会社名、住所、連絡先などを含む SQL Server テーブルがあります。

このテーブルとの照合を必要とする外部ソースから定期的にデータ ファイルを受け取ります。残念ながら、データは完全に異なるシステムからのものであるため、わずかに異なります。たとえば、「123 E. Main St.」があります。「123 East Main Street」と表示されます。別の例として、「Acme, LLC」があり、ファイルに「Acme Inc.」が含まれているとします。もう1つは、「エド・スミス」と「エドワード・スミス」です。

これらの一致を処理するために、かなり複雑で CPU を集中的に使用する方法を利用する従来のシステムがあります。純粋な SQL が関係するものもあれば、Access データベースの VBA コードが関係するものもあります。現在のシステムは優れていますが、完璧ではなく、面倒で維持が困難です。

ここの管理者は、その使用を拡大したいと考えています。システムのサポートを継承する開発者は、メンテナンスをあまり必要としない、より機敏なソリューションに置き換えることを望んでいます。

この種のデータ マッチングを処理する一般的に受け入れられている方法はありますか?

4

5 に答える 5

4

これは、ほぼ同一のスタックについて書いたものです (ハードウェアのメーカー名を標準化する必要があり、あらゆる種類のバリエーションがありました)。ただし、これはクライアント側です (正確には VB.Net)。レーベンシュタイン距離アルゴリズムを使用します (より良い結果を得るために変更されています)。

    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 データベース」というフレーズがシステムの説明に一緒に表示されるという事実も、優れたサードパーティ製ツールを見つけるもう 1 つの理由です。

編集: .NET にこの種のことを行う組み込みコンポーネントがある可能性もあります。その場合、料金を支払う必要はありません。.NET が提供するツールには、今でもときどき驚かされます。

于 2008-09-24T12:54:11.597 に答える
1

Access には、このためのツールが実際にはありません。理想的な世界では、SSIS ソリューションを使用してあいまい検索を使用します。しかし、現在 Access を使用している場合、オフィスで SQL Server Enterprise エディションを購入する可能性は低いと思われます。現在の環境に行き詰まっている場合は、ブルート フォース アプローチを試すことができます。

アドレスの標準化されたクレンジングから始めます。Street、raod などの標準的な略語を選択し、すべての通常のバリエーションをそれらの標準的なアドレスに変更するコードを記述します。2 つのスペースのインスタンスを 1 つのスペースに置き換え、すべてのデータをトリミングし、英数字以外の文字をすべて削除します。ご覧のとおり、これはかなりの作業です。

会社名については、名前の最初の 5 文字と住所または電話番号を一致させてみてください。また、既知のバリエーションのテーブルを作成し、将来のファイルのクレンジングに使用するためにデータベース内でそれらが関連することもできます。したがって、ID 100 のレコードが Acme, Inc. である場合、次のようなテーブルを作成できます。

ID フィールド名

100 アクメ株式会社

100 アクメ社

100 アクメ株式会社

100 アクメ、LLC

100アクメ

これは最初は小さいですが、重複を見つけて修正するたびにエントリを作成し (重複排除プロセスの一部にする)、時間の経過とともに増加します。既存の会社の名前と住所。

また、Torial が投稿したその関数を見て、それが役立つかどうかを確認します。

これはすべて面倒で時間がかかりますが、新しいバリエーションを見つけてコードまたはリストに追加すると、時間の経過とともに改善されます. 住所データを標準化することに決めた場合は、最初に本番データを消去してから、作業テーブルへのインポートを行って消去してから、本番データとの照合を試みて新しいレコードを挿入してください。

于 2008-09-24T13:51:31.007 に答える