L'appariement des enregistrements en fonction du nom personne
-
13-09-2019 - |
Question
Y a-t-il des outils ou des méthodes qui peuvent être utilisés pour la correspondance par le nom d'une personne entre deux sources de données différentes?
Les systèmes ont pas d'autres informations communes et les noms ont été saisis différemment dans de nombreux cas.
Des exemples de correspondances non exactes:
King Jr., Martin Luther = King, Martin (exclure le suffixe)
Erving, le Dr J. = Erving, J. (préfixe exclure)
Obama, Barak Hussein Obama =, Barak (exclure le nom du milieu)
Pufnstuf, H.R. = Pufnstuf, Ailes Grises (abréviations match)
Tankengine, Thomas = Tankengine, Tom (match de surnoms communs)
Flair, Rick "le Natureboy" = Flair, Natureboy (match sur surnom)
La solution
Je devais utiliser une variété de techniques proposées. Merci me pointant dans la bonne direction (s). Si tout va bien, ce qui suit vous aidera quelqu'un d'autre avec ce type de problème à résoudre.
Suppression de caractères en excès
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
Utilisation:
--remove all non-alphanumeric and non-white space
dbo.fn_StripCharacters(@Value, , '^a-z^0-9 ')
nom de Split en parties
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
Utilisation:
--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
surnoms communs:
J'ai créé une table basée sur cette liste et l'a utilisé pour joindre le nom commun équivalents.
Utilisation:
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
algorithmes phonétiques (Jaro Winkler):
L'article étonnant, Au-delà SoundEx - Fonctions pour la recherche floue dans MS SQL Server , montre comment installer et utiliser la bibliothèque SimMetrics dans SQL Server. Cette bibliothèque vous permet de trouver relative similitude entre les chaînes et comprend de nombreux algorithmes. J'ai fini par la plupart du temps en utilisant Jaro Winkler pour faire correspondre les noms.
Utilisation:
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))
Autres conseils
Il est un problème très complexe - et il y a beaucoup d'outils coûteux de le faire correctement
.
Si vous jamais demandé pourquoi vous ne pouvez pas vérifier sur un vol comme Tom, Dick ou Harry (ou Bill)
Ou pourquoi pas-mouche des listes et des terroristes listes de surveillance ne fonctionnent pas -examiner:
(1) Muammar Qaddafi
(2) Mo'ammar Khadafi
(3) Muammar Kaddafi
(4) Muammar Khadafi
(5) Moammar El
Kadhafi
(6) Muammar
Gadafi
(7) Mouammar Qadafi
(8) El Moammar Kazzafi
(9) Moamar Kadhafi
(10) Al Mouamar Kadhafi
(11) Muammar Kadhafi
(12) Mo'ammar el-Khadafi
(13) El Moamar
Kadhafi
(14) Mouammar Kadhafi
(15) al-Mouamar
Kadhafi
(16) Mouamar Khadafi
(17) Moamar Kadhafi
(18)
Mouamar Kadhafi
(19) Muammar Khaddafi
(20) Mouammar Khaddafi
(21) Mu'amar al-Kadafi
(22) Muammar Ghaddafy
(23) Muammar Khadafi
(24) Muammar Khaddafi
(25) Muamar
Kaddafi
(26) Muammar Quathafi
(27) Muammar
Gheddafi
(28) Al-Muamar
Kaddafi
(29) Moammar Khadafi
(30) Moammar Qudhafi
(31) al-Qaddafi Mouamar
(32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar Kaddafi
Et c'est juste orthographes officielles - il ne comprend pas les fautes de frappe
J'emploie souvent des algorithmes de type soundex pour ce type de situation. Essayez le Double Metaphone algorithme de. Si vous utilisez SQL Server, il y a un code source pour créer une fonction définie par l'utilisateur.
Parce que vous avez transposé les données, vous pouvez normaliser un peu, par exemple, supprimer toutes les virgules et les mots résultant par la première lettre. Cela vous donnera un potentiel meilleur appariement. Dans le cas où les mots ont été ajoutés au milieu, il devient un peu plus difficile. Vous pourriez envisager de casser un nom en mots, en vérifiant avec double Metaphone s'il y a un mot dans l'autre colonne correspondant, puis recueillir le nombre global de matchs contre les mots qui vous dira à quel point les deux colonnes sont.
Je filtrent aussi les mots comme le Dr, M., Mme, Mme, etc., avant de faire les comparaisons.
Voici quelques options:
algorithmes phonétiques ...
Soundex ( http://en.wikipedia.org/wiki/Soundex )
Double Metaphone ( http://en.wikipedia.org/wiki/Double_Metaphone )
Modifier Distance ( http://en.wikipedia.org/wiki/Levenshtein_distance )
Jaro-Winkler Distance ( http://en.wikipedia.org/wiki/Jaro- Winkler_distance )
Une autre chose que vous pourriez essayer serait de comparer chaque mot (fractionnement de l'espace et peut-être trait d'union) avec chaque mot dans l'autre nom et voir combien de mots correspondent. Peut-être combiner avec des algorithmes phonétiques pour la correspondance plus floue. Pour un vaste ensemble de données, vous voulez indexer chaque mot et correspondre avec un identifiant de nom. Pour abréviation vous pouvez comparer correspondant juste la première lettre. Vous voulez sans doute ignorer quoi que ce soit, mais des lettres lorsque vous comparez des mots aussi bien.
La plupart des algorithmes phonétiques ont open source / échantillons en ligne.
Metaphone 3 est la troisième génération de l'algorithme Metaphone. Il augmente la précision du codage phonétique de 89% de Double Metaphone 98% , tel que testé contre une base de données les plus courantes mots anglais, et les noms et les mots non anglais familiers dans le Nord Amérique. Cela produit un codage phonétique extrêmement fiable pour prononciations américains.
Metaphone 3 a été conçu et développé par Lawrence Philips, qui conçu et développé le Metaphone original et double Metaphone algorithmes.