Как сопоставить людей между отдельными системами, использующими SQL? - PullRequest
2 голосов
/ 08 октября 2009

Я хотел бы знать, есть ли способ сопоставлять людей между двумя отдельными системами, используя (в основном) SQL.

У нас есть две отдельные базы данных Oracle, в которых хранятся люди. Нет никакой связи между ними (то есть не может присоединиться к person_id); это намеренно Я хотел бы создать запрос, который проверяет, существует ли данная группа людей из системы A в системе B.

Я могу создавать таблицы, если это облегчает. Я также могу выполнять запросы и делать некоторые манипуляции с данными в Excel при создании моего окончательного отчета. Я не очень знаком с PL / SQL.

В системе A у нас есть информация о людях (имя, DOB, соц, пол и т. Д.). В системе B у нас одни и те же типы информации о людях. Могут быть ошибки при вводе данных (человек вводит неправильное написание), но я не буду беспокоиться об этом слишком сильно, за исключением, может быть, просто сравнения первых 4 букв. Этот вопрос более конкретно касается этой проблемы .

Они думали об этом через коррелированные подзапросы. Итак, примерно,

select a.lastname, a.firstname, a.soc, a.dob, a.gender
  case 
    when exists (select 1 from b where b.lastname = a.lastname) then 'Y' else 'N'
  end last_name,
  case 
    when exists (select 1 from b where b.firstname = a.firstname) then 'Y' else 'N'
  end first_name, 
  case [etc.]
from a

Это дает мне то, что я хочу, я думаю ... Я могу экспортировать результаты в Excel, а затем найти записи, которые имеют 3 или более совпадений. Я считаю, что это показывает, что данное поле из A было найдено в B. Однако я выполнил этот запрос только с тремя из этих полей, и для его выполнения потребовалось более 3 часов (я просматриваю данные за 2 года). Я хотел бы иметь возможность соответствовать по 5 критериям (фамилия, имя, пол, дата рождения, соц). Кроме того, хотя соц-номер является лучшим выбором для сопоставления, он также чаще всего пропускает часть данных. Каков наилучший способ сделать это? Спасибо.

Ответы [ 5 ]

2 голосов
/ 08 октября 2009

Пример предложения HLGEM JOIN:

SELECT a.lastname, 
       a.firstname, 
       a.soc, 
       a.dob, 
       a.gender
  FROM TABLE a
  JOIN TABLE b ON SOUNDEX(b.lastname) = SOUNDEX(a.lastname)
              AND SOUNDEX(b.firstname) = SOUNDEX(a.firstname)
              AND b.soc = a.soc
              AND b.dob = a.dob
              AND b.gender = a.gender

Ссылка: SOUNDEX

2 голосов
/ 08 октября 2009

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

Я выполнил аналогичную задачу по поиску дубликатов в нашей системе SQL Server и разбил ее на этапы. Итак, сначала я нашел всех, где имена и город / штат точно совпадали. Затем я искал дополнительные возможные совпадения (номер телефона, ssn, неточное совпадение имен и т. Д.). Как я нашел возможное совпадение между двумя профилями, я добавил его в промежуточную таблицу с кодом для того, какой тип совпадения нашел его. Затем я назначил доверительная сумма для каждого типа совпадения и сложение доверительной вероятности для каждого потенциального совпадения. Поэтому, если совпадения SOC, вы можете захотеть получить высокую достоверность, такую ​​же, если имя точное, а пол точный, а точная - точная. фамилия является точной, а имя не точным и т. д. Добавив уверенность, я намного лучше смог увидеть, какие возможные совпадения с большей вероятностью могут быть одним и тем же человеком. SQl Server также имеет функцию soundex, которая может помочь с имена немного отличаются. Держу пари, у Oracle есть нечто похожее.

После того, как я это сделал, я научился делать нечеткие группировки в SSIS и смог генерировать больше совпадений с более высоким уровнем достоверности. Я не знаю, есть ли в инструментах Oracle ETL способ создания нечеткой логики, но если они это сделают, это действительно может помочь с этим типом задач. Если у вас также есть SQL Server, SSIS может быть запущен с подключением к Oracle, поэтому вы можете использовать нечеткую группировку самостоятельно. Хотя запуск может занять много времени.

Я предупрежу вас, что имя, фамилия и пол вряд ли будут гарантировать, что они являются одним и тем же лицом, особенно для общих имен.

1 голос
/ 08 октября 2009

Вы определенно хотите взвесить разные спички. Если SSN совпадает, это довольно хороший показатель. Если firstName совпадает, это в принципе ничего не стоит.

Вы можете попробовать метод оценки, основанный на весах совпадений, в сочетании с алгоритмами сопоставления фонетических строк, с которыми вы связались. Вот пример, который я описал в T-SQL. Это должно быть перенесено в Oracle для вашей проблемы.

--Score Threshold to be returned
DECLARE @Threshold DECIMAL(5,5) = 0.60

--Weights to apply to each column match (0.00 - 1.00)
DECLARE @Weight_FirstName DECIMAL(5,5) = 0.10
DECLARE @Weight_LastName DECIMAL(5,5) = 0.40
DECLARE @Weight_SSN DECIMAL(5,5) = 0.40
DECLARE @Weight_Gender DECIMAL(5,5) = 0.10

DECLARE @NewStuff TABLE (ID INT IDENTITY PRIMARY KEY, FirstName VARCHAR(MAX), LastName VARCHAR(MAX), SSN VARCHAR(11), Gender VARCHAR(1))
INSERT INTO @NewStuff
    ( FirstName, LastName, SSN, Gender )
VALUES  
    ( 'Ben','Sanders','234-62-3442','M' )

DECLARE @OldStuff TABLE (ID INT IDENTITY PRIMARY KEY, FirstName VARCHAR(MAX), LastName VARCHAR(MAX), SSN VARCHAR(11), Gender VARCHAR(1))
INSERT INTO @OldStuff
    ( FirstName, LastName, SSN, Gender )
VALUES
    ( 'Ben','Stickler','234-62-3442','M' ), --3/4 Match
    ( 'Albert','Sanders','523-42-3441','M' ), --2/4 Match
    ( 'Benne','Sanders','234-53-2334','F' ), --2/4 Match
    ( 'Ben','Sanders','234623442','M' ), --SSN has no dashes
    ( 'Ben','Sanders','234-62-3442','M' ) --perfect match

SELECT 
    'NewID' = ns.ID,
    'OldID' = os.ID,

    'Weighted Score' = 
        (CASE WHEN ns.FirstName = os.FirstName THEN @Weight_FirstName ELSE 0 END)
        +
        (CASE WHEN ns.LastName = os.LastName THEN @Weight_LastName ELSE 0 END)
        +
        (CASE WHEN ns.SSN = os.SSN THEN @Weight_SSN ELSE 0 END)
        +
        (CASE WHEN ns.Gender = os.Gender THEN @Weight_Gender ELSE 0 END)
    ,   

    'RAW Score' = CAST(
        ((CASE WHEN ns.FirstName = os.FirstName THEN 1 ELSE 0 END)
        +
        (CASE WHEN ns.LastName = os.LastName THEN 1 ELSE 0 END) 
        +
        (CASE WHEN ns.SSN = os.SSN THEN 1 ELSE 0 END) 
        +
        (CASE WHEN ns.Gender = os.Gender THEN 1 ELSE 0 END) ) AS varchar(MAX))
        + 
        ' / 4',

    os.FirstName ,
    os.LastName ,
    os.SSN ,
    os.Gender

FROM @NewStuff ns

--make sure that at least one item matches exactly
INNER JOIN @OldStuff os ON 
    os.FirstName = ns.FirstName OR
    os.LastName = ns.LastName OR
    os.SSN = ns.SSN OR
    os.Gender = ns.Gender
where 
    (CASE WHEN ns.FirstName = os.FirstName THEN @Weight_FirstName ELSE 0 END)
    +
    (CASE WHEN ns.LastName = os.LastName THEN @Weight_LastName ELSE 0 END)
    +
    (CASE WHEN ns.SSN = os.SSN THEN @Weight_SSN ELSE 0 END)
    +
    (CASE WHEN ns.Gender = os.Gender THEN @Weight_Gender ELSE 0 END)
    >= @Threshold
ORDER BY ns.ID, 'Weighted Score' DESC

А затем вот вывод.

NewID OldID Weighted  Raw    First  Last      SSN          Gender
1     5     1.00000   4 / 4  Ben    Sanders   234-62-3442  M
1     1     0.60000   3 / 4  Ben    Stickler  234-62-3442  M
1     4     0.60000   3 / 4  Ben    Sanders   234623442    M

Затем вам нужно будет выполнить некоторую постобработку, чтобы оценить достоверность каждого возможного совпадения. Если вы когда-нибудь получите 1,00 за взвешенный счет, вы можете предположить, что это правильный матч, если только вы не получите два из них. Если вы получите фамилию и SSN (общий вес 0,8 в моем примере), вы можете быть достаточно уверены, что это правильно.

0 голосов
/ 08 октября 2009

Вы можете использовать soundex, но вы также можете использовать utl_match для нечеткого сравнения строк, utl_match позволяет определить порог: http://www.psoug.org/reference/utl_match.html

0 голосов
/ 08 октября 2009

Есть ли индексы для всех столбцов в таблице b в предложении WHERE? Если нет, это приведет к полному сканированию таблицы для каждой строки в таблице a.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...