Вопрос

У нас есть таблица SQL Server, содержащая название компании, адрес и имя контактного лица (среди прочего).

Мы регулярно получаем файлы данных из внешних источников, которые требуют от нас сверки с этой таблицей.К сожалению, данные немного отличаются, поскольку поступают из совершенно другой системы.Например, у нас есть «123 Е.Мейн-стрит», и мы получаем «123 Ист-Мейн-стрит».Другой пример: у нас есть «Acme, LLC», а файл содержит «Acme Inc.».Другой вариант: у нас есть «Эд Смит», а у них есть «Эдвард Смит».

У нас есть устаревшая система, в которой для обработки таких совпадений используются довольно сложные и ресурсоемкие методы.Некоторые используют чистый SQL, а другие используют код VBA в базе данных Access.Существующая система хороша, но не идеальна, громоздка и сложна в обслуживании.

Руководство здесь хочет расширить его использование.Разработчики, которые унаследуют поддержку системы, хотят заменить ее более гибким решением, требующим меньшего обслуживания.

Существует ли общепринятый способ справиться с таким сопоставлением данных?

Это было полезно?

Решение

Вот что я написал для почти идентичного стека (нам нужно было стандартизировать названия производителей оборудования, и были всевозможные вариации).Однако это клиентская сторона (точнее, 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

Другие советы

SSIS (в Sql 2005+ Enterprise) имеет Нечеткий поиск который предназначен именно для таких задач очистки данных.

Помимо этого, я знаю только решения, специфичные для предметной области, такие как очистка адреса, или общий методы сопоставления строк.

Существует множество поставщиков, предлагающих продукты для такого рода сопоставления с образцом.Я бы провел небольшое исследование и Найдите хороший продукт с хорошей репутацией и откажитесь от отечественной системы..

Как вы говорите, ваш продукт только хорош, и это достаточно распространенная потребность в бизнесе, и я уверен, что существует более одного превосходного продукта.Даже если лицензия будет стоить несколько тысяч долларов, это все равно будет дешевле, чем платить группе разработчиков за работу над чем-то собственными силами.

Кроме того, тот факт, что фразы «сложный», «интенсивный процессор», «код VBA» и «база данных доступа» встречаются вместе в описании вашей системы, является еще одной причиной найти хороший сторонний инструмент.

РЕДАКТИРОВАТЬ:Также возможно, что в .NET есть встроенный компонент, который делает подобные вещи, и в этом случае вам не придется за него платить.Я до сих пор время от времени удивляюсь инструментам, которые предлагает .NET.

Я имею дело с точно такой же проблемой.Взгляни на:

Инструменты для сопоставления данных имени/адреса

для некоторых инструментов, которые могут помочь.

В Access на самом деле нет инструментов для этого.В идеальном мире я бы выбрал решение SSIS и использовал нечеткий поиск.Но если вы в настоящее время используете Access, шансы на то, что ваш офис купит версию SQL Server Enterprise, кажутся мне низкими.Если вы застряли в текущей среде, вы можете попробовать метод грубой силы.

Начните со стандартизированной очистки адресов.Подберите стандартные сокращения для Street, raod и т. д.и напишите код, чтобы изменить все обычные варианты этих стандартных адресов.Замените любые экземпляры двух пробелов одним пробелом, обрежьте все данные и удалите все небуквенно-цифровые символы.Как видите, это довольно сложная задача.

Что касается названий компаний, возможно, вы можете попробовать сопоставить первые 5 символов имени и адреса или телефона.Вы также можете создать таблицу известных вариантов и того, к чему они будут относиться в вашей базе данных, чтобы использовать ее для очистки будущих файлов.Итак, если вы записываете с идентификатором 100, это Acme, Inc.у вас может быть такая таблица:

Имя поля идентификатора

100 Акме, Инк.

100 Акме, Инк.

100 Акме, Инкорпорейтед

100 Акме, ООО

100 акме

Это начнется с малого, но со временем будет развиваться, если вы будете делать запись каждый раз, когда найдете и исправить дубликат (сделайте это частью процесса удаления дубликатов), и если вы будете делать запись каждый раз, когда сможете сопоставить первую часть название и адрес существующей компании.

Я бы также посмотрел на эту функцию, опубликованную Ториалом, и посмотрел, поможет ли она.

Все это будет болезненным и трудоемким, но со временем станет лучше, когда вы найдете новые варианты и добавите их в код или список.Если вы все же решили классифицировать свои адресные данные, сначала очистите производственные данные, затем выполните импорт в рабочую таблицу и очистите ее, а затем попытайтесь сопоставить производственные данные и вставить новые записи.

Я только что нашел это связь это связано.

Клянусь, я посмотрел, прежде чем опубликовать это.

Есть довольно много способов решить эту проблему, которые могут быть неочевидными.Лучше всего найти уникальные идентификаторы, которые можно использовать для сопоставления за пределами полей с ошибками в написании и т. д.

Некоторые мысли

  1. Очевидное: номер социального страхования, водительские права и т. д.
  2. Адрес электронной почты
  3. Очищенный номер телефона (удалена пунктуация и т. д.)

Что касается поставщиков, я только что ответил на аналогичный вопрос и вставляю ниже.

У каждого крупного провайдера есть свое собственное решение.Oracle, IBM, SAS Dataflux и т. д., и каждая из них претендует на звание лучшего в решении подобных задач.

Независимая проверенная оценка:

В Центре связи данных Университета Кертина в Австралии было проведено исследование, в котором моделировалось сопоставление 4,4 миллиона записей.Определили, что было у поставщиков с точки зрения точности (количество найденных совпадений и доступных.Количество ложных совпадений)

ДатаМатч Предприятие, Высочайшая точность (>95%), очень быстрая, низкая стоимость

Этап качества IBM , высокая точность (>90%), очень быстрая, высокая стоимость (>100 тыс. долларов США)

Поток данных SAS, точность средней (> 85%), быстрая, высокая стоимость (> 100K), которая была лучшей независимой оценкой, которую мы могли найти, была очень тщательной.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top