18

是否有任何工具或方法可用于在两个不同数据源之间通过人名进行匹配?

这些系统没有其他共同信息,而且在许多情况下输入的名称不同。

非精确匹配示例:

King Jr., Martin Luther = King, Martin (不包括后缀)
Erving, Dr. J. = Erving, J. (不包括前缀)
Obama, Barak Hussein = Obama, Barak (不包括中间名)
Pufnstuf, HR = Pufnstuf, Haibane Renmei (匹配缩写)
Tankengine,Thomas = Tankengine,Tom(匹配常用昵称)
Flair,Rick “the Natureboy” = Flair,Natureboy(匹配昵称)

4

5 回答 5

15

我不得不使用建议的各种技术。感谢为我指明正确的方向。希望以下内容可以帮助其他人解决此类问题。

去除多余的字符

CREATE FUNCTION [dbo].[fn_StripCharacters]
(
    @String NVARCHAR(MAX), 
    @MatchExpression VARCHAR(255)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    SET @MatchExpression =  '%['+@MatchExpression+']%'

    WHILE PatIndex(@MatchExpression, @String) > 0
        SET @String = Stuff(@String, PatIndex(@MatchExpression, @String), 1, '')

    RETURN @String

END

用法:

--remove all non-alphanumeric and non-white space  
dbo.fn_StripCharacters(@Value, , '^a-z^0-9 ')  

将名称拆分为多个部分

CREATE FUNCTION [dbo].[SplitTable] (@sep char(1), @sList StringList READONLY)
RETURNS @ResultList TABLE 
    (
        [ID] VARCHAR(MAX),
        [Val] VARCHAR(MAX)
    )
AS
BEGIN

declare @OuterCursor cursor
declare @ID varchar(max)
declare @Val varchar(max)

set @OuterCursor = cursor fast_forward for (SELECT * FROM @sList) FOR READ ONLY

open @OuterCursor

fetch next from @OuterCursor into @ID, @Val

while (@@FETCH_STATUS=0)
begin

    INSERT INTO @ResultList (ID, Val)   
    select @ID, split.s from dbo.Split(@sep, @Val) as split 
           where len(split.s) > 0

    fetch next from @OuterCursor into @ID, @Val
end

close @OuterCursor
deallocate @OuterCursor 

CREATE FUNCTION [dbo].[Split] (@sep char(1), @s varchar(8000))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      LTRIM(RTRIM(SUBSTRING(@s, start, 
             CASE WHEN stop > 0 
                  THEN stop-start 
                  ELSE 8000 
             END))) AS s
    FROM Pieces
  )

RETURN

用法:

--create split name list
DECLARE @NameList StringList 

INSERT INTO @NameList (ID, Val)
SELECT id, firstname FROM dbo.[User] u
WHERE PATINDEX('%[^a-z]%', u.FirstName) > 0 

----remove split dups
select u.ID, COUNT(*)
from dbo.import_SplitTable(' ', @NameList) splitList
INNER JOIN dbo.[User] u
ON splitList.id = u.id

常用昵称:

我根据这个列表创建了一个表,并用它来加入通用名称等价物。

用法:

SELECT u.id
, u.FirstName
, u_nickname_maybe.Name AS MaybeNickname
, u.LastName
, c.ID AS ContactID from
FROM dbo.[User] u 
INNER JOIN nickname u_nickname_match
ON u.FirstName = u_nickname_match.Name
INNER JOIN nickname u_nickname_maybe
ON u_nickname_match.relatedid = u_nickname_maybe.id
LEFT OUTER JOIN
(
    SELECT c.id, c.LastName, c.FirstName, 
         c_nickname_maybe.Name AS MaybeFirstName
    FROM dbo.Contact c
    INNER JOIN nickname c_nickname_match
    ON c.FirstName = c_nickname_match.Name
    INNER JOIN nickname c_nickname_maybe
    ON c_nickname_match.relatedid = c_nickname_maybe.id
    WHERE c_nickname_match.Name <> c_nickname_maybe.Name
) as c
ON c.AccountHolderID = ah.ID 
       AND u_nickname_maybe.Name = c.MaybeFirstName AND u.LastName = c.LastName
WHERE u_nickname_match.Name <> u_nickname_maybe.Name

语音算法(Jaro Winkler):

令人惊叹的文章Beyond SoundEx - 在 MS SQL Server 中进行模糊搜索的函数,展示了如何在 SQL Server 中安装和使用SimMetrics库。该库可让您找到字符串之间的相对相似性,并包含许多算法。我最终主要使用Jaro Winkler来匹配名称。

用法:

SELECT
u.id AS UserID
,c.id AS ContactID
,u.FirstName
,c.FirstName 
,u.LastName
,c.LastName
,maxResult.CombinedScores
 from
(
    SELECT
      u.ID
    , 
        max(
            dbo.JaroWinkler(lower(u.FirstName), lower(c.FirstName))  
            * dbo.JaroWinkler(LOWER(u.LastName), LOWER(c.LastName))
        ) AS CombinedScores
    FROM dbo.[User] u, dbo.[Contact] c
    WHERE u.ContactID IS NULL
    GROUP BY u.id
) AS maxResult
INNER JOIN dbo.[User] u
ON maxResult.id  = u.id
INNER JOIN dbo.[Contact] c
ON maxResult.CombinedScores = 
dbo.JaroWinkler(lower(u.FirstName), lower(c.FirstName)) 
* dbo.JaroWinkler(LOWER(u.LastName), LOWER(c.LastName))
于 2009-06-19T15:55:26.377 回答
2

这是一个非常复杂的问题 - 有很多昂贵的工具可以正确完成。
如果您想知道为什么不能以汤姆、迪克或哈利(或比尔)的身份登机,
或者为什么禁飞名单和恐怖分子观察名单不起作用 - 请考虑:

(1) 穆阿迈尔卡扎菲
(2) 穆阿迈尔卡扎菲
(3) 穆阿迈尔卡扎菲
(4) 穆阿迈尔卡扎菲
(5) 穆阿迈尔卡扎菲
(6) 穆阿迈尔卡扎菲
(7)穆阿迈尔卡扎菲 (8)
穆阿迈尔卡扎菲
(9 ) ) 穆阿迈尔·卡扎菲
(10) 穆阿迈尔·卡扎菲
(11) 穆阿迈尔·卡扎菲
(12) 穆阿迈尔·卡扎菲
(13) 穆阿迈尔·卡扎菲
(14) 穆阿迈尔·卡扎菲
(15)穆阿迈尔·卡扎菲
(16) 穆阿迈尔
卡扎菲 (17) 穆阿迈尔卡扎菲
(18) 穆阿迈尔卡扎菲
(19) 穆阿迈尔卡扎菲
(20) 穆阿迈尔卡扎菲
(21)
穆阿迈尔卡扎菲 (22) 穆阿迈尔卡扎菲
(23) 穆阿迈尔卡扎菲
(24) 穆阿迈尔·卡扎菲
(25)穆阿迈尔·卡扎菲
(26) 穆阿迈尔·夸塔菲
(27) 穆阿迈尔·格扎菲
(28) 穆阿迈尔·卡扎菲
(29) 穆阿迈尔·卡扎菲
(30) 穆阿迈尔·库扎菲
(31) 穆阿迈尔·卡扎菲
(32) 穆拉齐姆·奥瓦尔·穆阿迈尔·穆罕默德阿布·米尼亚尔·卡扎菲

这只是官方拼写 - 它不包括拼写错误!

于 2010-03-31T18:56:55.270 回答
1

对于这种情况,我经常使用 soundex 类型的算法。尝试双变音器算法。如果您使用的是 SQL Server,则有一些源代码可以创建用户定义的函数。

因为您已经转置了数据,您可能需要对其进行一些规范化,例如,删除所有逗号并按第一个字母对结果单词进行排序。这会给你一些更好的匹配潜力。在中间添加单词的情况下,它变得有点困难。您可以考虑将名称分解为单词,使用 Double Metaphone 检查另一列中是否有匹配的单词,然后收集匹配与单词的总计数,这将告诉您两列的接近程度。

在进行比较之前,我还会过滤掉诸如 Dr.、Mr.、Ms.、Mrs. 等常用词。

于 2009-06-12T17:50:15.730 回答
1

以下是一些选项:

语音算法...

Soundex ( http://en.wikipedia.org/wiki/Soundex )

双变音器(http://en.wikipedia.org/wiki/Double_Metaphone

编辑距离(http://en.wikipedia.org/wiki/Levenshtein_distance

Jaro-Winkler 距离 ( http://en.wikipedia.org/wiki/Jaro-Winkler_distance )

您可以尝试的另一件事是将每个单词(以空格分隔,可能还有连字符)与另一个名称中的每个单词进行比较,看看有多少单词匹配。也许将其与语音算法相结合以获得更模糊的匹配。对于庞大的数据集,您可能希望索引每个单词并将其与名称 id 匹配。对于缩写匹配,您可以只比较第一个字母。当您比较单词时,您可能想忽略除字母之外的任何内容。

许多语音算法都有在线开源/示例。

于 2009-06-12T17:55:52.863 回答
1

Metaphone 3是 Metaphone 算法的第三代。它将语音编码的准确性从 Double Metaphone 的 89% 提高到98%,这是针对北美最常见的英语单词、名称和非英语单词的数据库进行测试的。这为美式发音产生了极其可靠的语音编码。

Metaphone 3 由设计和开发原始 Metaphone 和 Double Metaphone 算法的 Lawrence Philips 设计和开发。

于 2013-02-06T04:43:17.587 回答