问题描述
我正在开发一个匹配程序,该程序使用字段的组合来匹配2个数据集,例如名字,姓氏,税号,SSN,DOB,地址...数据集总是不同的,并且我可用于匹配的字段会有所不同。我在MS Access中有一个应用程序,在其中我映射了可用于我的字段列表的字段名称。
我对每个字段的强度从0到100进行了排名(当然,这都是主观的,因为我无法知道一个字段的独特性。例如,DOB为50%,但DOB确实是50%不重复?姓氏怎么不重复?因此,正确排名是我的第一个问题,因为匹配的顺序取决于该排名)。
下面是我的表,其中包含所有字段,我分配给它们的强度(从0到100)和排序顺序(基本上与强度相关,按照从最强到最弱的顺序排序)。
映射后,我运行的代码创建了SortIDPracs字段的置换,因此,我最终获得了该数据集的所有可能字段组合。 以下是匹配类别的示例。如您所见,我每个类别运行了4次:
1。名字和姓氏
2。名字的第一个姓氏
3个名字,姓氏的前4个字母
4。没有名字
下面是创建上面清单的代码。您可以插入不同的SortIdPracs值,显然,您会获得不同的组合列表。
DECLARE
VarCountOfFields NUMBER;
VarCurrentFieldNo NUMBER;
VarFirstNo NUMBER;
VarCountOfRanked VARCHAR2(1000);
VarSQLSelect1 VARCHAR2(1000);
VarSQLSelect2 VARCHAR2(4000);
VarSQLSelect2MatchedText VARCHAR2(4000);
VarSQLSelect2SQL1 VARCHAR2(4000);
VarSQLSelect2SQL2 VARCHAR2(4000);
VarSQLSelect2MatchWorth VARCHAR2(4000);
VarSQLFrom2 VARCHAR2(1000);
VarSQLJoins2 VARCHAR2(1000);
VarSQLText CLOB;
BEGIN
TruncateTable_P('MATCH_300');
INSERT INTO MATCH_300
SELECT LEVEL Lvl,SYS_CONNECT_BY_PATH(col1,',') PathNo
FROM (SELECT SortIDPracs Col1,SortIDPracs Col2
FROM (SELECT 101 SortIDPracs FROM DUAL
UNION ALL
SELECT 102 SortIDPracs FROM DUAL
UNION ALL
SELECT 104 SortIDPracs FROM DUAL
UNION ALL
SELECT 105 SortIDPracs FROM DUAL
UNION ALL
SELECT 106 SortIDPracs FROM DUAL
UNION ALL
SELECT 107 SortIDPracs FROM DUAL)) tmp
CONNECT BY PRIOR col1 < col2
ORDER BY LEVEL,');
--can't combine,string concatenation too long error
TruncateTable_P('MATCH_301');
INSERT INTO MATCH_301
SELECT ROWNUM UniqueID,SUBSTR(PathNo,3,99) Permutations,(TRIM(LENGTH(SUBSTR(PathNo,99))) - TRIM(LENGTH(TRANSLATE(SUBSTR(PathNo,99),'A,'A')))) + 1 CountOfFields
FROM (SELECT DISTINCT tmp.*
FROM MATCH_300 tmp
ORDER BY 1 DESC,2);
SELECT COUNT(DISTINCT mf.SortIDPracs)
INTO VarCountOfFields
FROM MATCH_MAPPING tmp,MATCH_FIELDS mf
WHERE 1 = 1
AND mf.SortIDPracs IS NOT NULL
AND tmp.MatchFieldID = mf.MatchFieldID
AND tmp.ProjectCriteriaID = 6;
VarCurrentFieldNo := 1;
WHILE VarCurrentFieldNo <= VarCountOfFields LOOP
IF VarCurrentFieldNo <= 2 THEN
VarFirstNo := 1;
ELSE
VarFirstNo := 2;
END IF;
IF VarSQLSelect1 IS NULL THEN
VarSQLSelect1 := ',REGEXP_SUBSTR(tmp.Permutations,''[^ ]+'',' || VarFirstNo || ',' || VarCurrentFieldNo || ') Permutations' || VarCurrentFieldNo;
VarSQLSelect2 :=
',mt'
|| VarCurrentFieldNo
|| '.FieldName FieldName'
|| VarCurrentFieldNo
|| ',mt'
|| VarCurrentFieldNo
|| '.FieldStrengthPracs FieldStrengthPracs'
|| VarCurrentFieldNo
|| ',mt'
|| VarCurrentFieldNo
|| '.StrengthRankPracs StrengthRankPracs'
|| VarCurrentFieldNo;
VarSQLFrom2 := ',MATCH_FIELDS mt' || VarCurrentFieldNo;
VarSQLJoins2 := 'AND tmp.Permutations' || VarCurrentFieldNo || ' = mt' || VarCurrentFieldNo || '.SortIDPracs(+)';
VarSQLSelect2MatchedText := 'FieldName' || VarCurrentFieldNo;
VarSQLSelect2SQL1 := 'FieldName' || VarCurrentFieldNo;
VarSQLSelect2SQL2 := 'mt.'' || FieldName' || VarCurrentFieldNo || ' || '' = pr.'' || FieldName' || VarCurrentFieldNo;
VarSQLSelect2MatchWorth := '+ NVL(FieldStrengthPracs' || VarCurrentFieldNo || ',0) ';
VarCountOfRanked := '+ NVL(StrengthRankPracs' || VarCurrentFieldNo || ',0) ';
ELSE
VarSQLSelect1 :=
VarSQLSelect1
|| ','
|| VarFirstNo
|| ','
|| VarCurrentFieldNo
|| ') Permutations'
|| VarCurrentFieldNo;
VarSQLSelect2 :=
VarSQLSelect2
|| ',mt'
|| VarCurrentFieldNo
|| '.StrengthRankPracs StrengthRankPracs'
|| VarCurrentFieldNo;
VarSQLFrom2 := VarSQLFrom2 || ',MATCH_FIELDS mt' || VarCurrentFieldNo;
VarSQLJoins2 := VarSQLJoins2 || 'AND tmp.Permutations' || VarCurrentFieldNo || ' = mt' || VarCurrentFieldNo || '.SortIDPracs(+)';
VarSQLSelect2MatchedText :=
VarSQLSelect2MatchedText
|| ' || CASE WHEN FieldName'
|| VarCurrentFieldNo
|| ' IS NOT NULL THEN '','' || FieldName'
|| VarCurrentFieldNo
|| ' END';
VarSQLSelect2SQL1 :=
VarSQLSelect2SQL1 || ' || CASE WHEN FieldName' || VarCurrentFieldNo || ' IS NOT NULL THEN '','' || FieldName' || VarCurrentFieldNo || ' END';
VarSQLSelect2SQL2 :=
VarSQLSelect2SQL2
|| ' || CASE WHEN FieldName'
|| VarCurrentFieldNo
|| ' IS NOT NULL THEN '' AND mt.'' || FieldName'
|| VarCurrentFieldNo
|| ' || '' = pr.'' || FieldName'
|| VarCurrentFieldNo
|| ' END ';
VarSQLSelect2MatchWorth := VarSQLSelect2MatchWorth || '+ NVL(FieldStrengthPracs' || VarCurrentFieldNo || ',0) ';
VarCountOfRanked := VarCountOfRanked || '+ NVL(StrengthRankPracs' || VarCurrentFieldNo || ',0) ';
END IF;
VarCurrentFieldNo := VarCurrentFieldNo + 1;
COMMIT;
END LOOP;
DropObject_P('TABLE','MATCH_302');
VarSQLText := 'CREATE TABLE MATCH_302
AS
SELECT UniqueID,CountOfFields ' || VarSQLSelect1 || '
FROM (SELECT DISTINCT UniqueID,CountOfFields,REPLACE(Permutations,'','' '') Permutations
FROM MATCH_301) tmp
ORDER BY 1';
-- DBMS_OUTPUT.put_line(VarSQLText);
EXECUTE IMMEDIATE VarSQLText;
COMMIT;
DropObject_P('TABLE','MATCH_303');
VarSQLText := 'CREATE TABLE MATCH_303
AS
SELECT UniqueID,CountOfFields ' || VarSQLSelect2 || '
FROM MATCH_302 tmp ' || VarSQLFrom2 || '
WHERE 1=1 ' || VarSQLJoins2 || '
ORDER BY 1';
-- DBMS_OUTPUT.put_line(VarSQLText);
EXECUTE IMMEDIATE VarSQLText;
COMMIT;
DropObject_P('TABLE','MATCH_304');
VarSQLText :=
'CREATE TABLE MATCH_304
AS
SELECT UniqueID,CountOfFields+2 CountOfFields,1 PassNo,''First Name,Last Name,'' || '
|| VarSQLSelect2MatchedText
|| ' MatchedText,''FN,LN,'' || '
|| VarSQLSelect2SQL1
|| ' SQL1,''mt.FN = pr.FN AND mt.LN = pr.LN AND '
|| VarSQLSelect2SQL2
|| ' SQL2,(30'
|| VarSQLSelect2MatchWorth
|| ') MatchWorth,(0'
|| VarCountOfRanked
|| ') CountOfRanked
FROM MATCH_303 tmp
UNION ALL SELECT UniqueID,CountOfFields+2,2 PassNo,''First Initial,'' || '
|| VarSQLSelect2MatchedText
|| ' MatchedText,''FN1,'' || '
|| VarSQLSelect2SQL1
|| ' SQL1,''mt.FN1 = pr.FN1 AND mt.LN = pr.LN AND '
|| VarSQLSelect2SQL2
|| ' SQL2,(25'
|| VarSQLSelect2MatchWorth
|| ') MatchWorth,3 PassNo,First 4 Letters Of Last Name,'' || '
|| VarSQLSelect2MatchedText
|| ' MatchedText,LN4,''mt.FN = pr.FN AND mt.LN4 = pr.LN4 AND '
|| VarSQLSelect2SQL2
|| ' SQL2,(10'
|| VarSQLSelect2MatchWorth
|| ') MatchWorth,4 PassNo,'
|| VarSQLSelect2MatchedText
|| ' MatchedText,'
|| VarSQLSelect2SQL1
|| ' SQL1,'''
|| VarSQLSelect2SQL2
|| ' SQL2,(0'
|| VarSQLSelect2MatchWorth
|| ') MatchWorth,(0'
|| VarCountOfRanked
|| ') CountOfRanked
FROM MATCH_303 tmp ';
-- DBMS_OUTPUT.put_line(VarSQLText);
EXECUTE IMMEDIATE VarSQLText;
COMMIT;
END;
此查询将为您提供以上屏幕截图中的数据
SELECT DISTINCT tmp.*
FROM MATCH_304 tmp
ORDER BY 1,3;
然后,我使用SQL2字段中的联接向下循环浏览每个匹配的类别。 SQL1字段是字段列表。所以我有一个循环遍历每个类别的过程,并将这两个字段中的值插入到查询中
对其中一个类别的示例查询如下(因此,这是FN,LN,SSN,地址匹配的循环)。
INSERT INTO MATCH_MATCHED
SELECT --+append ordered use_hash(mt,pr)
DISTINCT mt.UniqueID,pr.UniqueID,3040,2
FROM MATCH_MATCH mt,(SELECT DISTINCT UniqueID,FN,SSN,Address
FROM MATCH_PROVS pr) pr
WHERE 1 = 1
AND mt.FN = pr.FN
AND mt.LN = pr.LN
AND mt.Address = pr.Address
AND mt.SSN = pr.SSN;
我有几个问题
- 需要帮助分配每个领域的力量(我敢肯定,头脑是不够的)。如果我知道总共有100个TIN(例如),并且我知道在最坏的情况下,将有20个提供商共享一个TIN,我如何计算仅TIN上的匹配才是正确的匹配百分比,是否为80在此示例中为%?
- 需要找到一种将强度%得分分配给每个匹配类别的方法。我曾想过要对所有字段的分数求和,然后除以字段数,但结果并非在所有地方都是正确的。例如,SSN的得分将高于FN,LN,SSN,DOB和城市。
- 我需要找到一种方法,使该分数随每个数据集而变化。例如,如果为我提供了一个包含FN,LN,SSN,DOB,地址,城市,州,邮政编码的数据集,那么我对FN,LN,地址的匹配不会太满意,因为它应该在SSN和/或DOB上也匹配。因此,本场比赛的得分应该不会太高,因为还有更多领域可以匹配。但是,如果给我一个具有FN,LN,地址的集合,那么FN,LN,地址上的匹配项将成为100%匹配项。因此,该分数必须考虑比赛开始时可用的字段
- 分数必须足够精确,以至于我可以相信它可以在运行时动态排除某些类别。例如,我永远不想单靠信任城市,州比赛。因此,理想情况下,我想在运行时查看分数,甚至不运行此行,因为它的分数会低于某个阈值
我无法提出一个可以让我完成所有这些工作的评分系统。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)