我有两个表,已经填充了如下数据:
table1
数据是公民数据,包含字段:
uniqid (a uniqueIP for person, like social sec num)
first_name
last_name
birthdate
address
带有字段的 table2
:
first_name
last_name
birthdate
address
gender
healthinsurance_type
...
table1
数据和table2
数据来自不同且独立的代理商。这些表中的名称可以以不同方式键入,依此类推。
table1
对名称和ID具有权威性。 table2
是我需要处理的问题,但没有ID(citizenID
)。
现在,我需要table2
中的每一行获得一个citizenid
,并table1
关联,这样我最终会得到table2
其他ID列,正确关联与每个人。
在table1
中搜索某个条件匹配的人(table2
中的行),如果table1
中存在记录,则将该记录的ID放入table2
中的列。
但要快速并且适用于所有行 table1的行数约为200万 table2的行数约为900.000
答案 0 :(得分:0)
我假设你是唯一一个写表的人,所以没有并发冲突......
将ID列添加到table2
,现在可以为NULL:
ALTER TABLE table2 ADD COLUMN citizenid int; -- or whatever the type is
考虑在table1
上添加一个标记,以便在市场上排除""另一方面也很便宜:
ALTER TABLE table1 ADD COLUMN hasmatch boolean;
假设两边都没有重复。否则你需要做更多。
使用完美匹配更新table2中的所有行。标记也会立即匹配table1
中的行。使用data-modifying CTE:
WITH u2 AS (
UPDATE table2 t2
SET citizenid = t1.uniqid
FROM table1 t1
WHERE t1.hasmatch IS NULL -- always with this condition
AND t2.citizenid IS NULL -- always with this condition
AND t2.first_name = t1.first_name
AND t2.last_name = t1.last_name
AND t2.birthdate = t1.birthdate
AND t2.address = t1.address
RETURNING citizenid
)
UPDATE table1 t1
SET hasmatch = TRUE
FROM u2
WHERE t2.citizenid = u2.citizenid;
只要一行有citizenid
它就会离开市场"在双方。
字符类型列的模糊匹配的可能选项是:
lower(t2.address) = lower(t1.address)
t2.address ILIKE (t1.address || %) -- here % is a wilcard for LIKE pattern
t1.address ILIKE (t2.address || %)
lower(left(t2.address, 20)) = lower(left(t1.address, 20))
t2.address % t1.address -- here % is the similarity operator
levenshtein(t2.address, t1.address) <= 3 -- *very* expensive, no index support
等。
相似性运算符%
由附加模块pg_trgm提供,它还提供三元组索引以支持LIKE
和相似性匹配。您将 需要索引进行模糊匹配,或者您的查询可能需要长时间。
一旦找到匹配项,请考虑使用部分索引从索引中删除行。像:
CREATE INDEX t1_adr_gin_trgm_idx ON table1 USING gin (address gin_trgm_ops)
WHERE t1.hasmatch IS NULL;
CREATE INDEX t2_adr_gin_trgm_idx ON table2 USING gin (address gin_trgm_ops)
WHERE t2.citizenid IS NULL;
等
您可以使用以下方法微调%
运算符的相似度阈值。
SELECT set_limit(0.8);
一小部分将无法解决。您可以花费越来越多的时间手动分配它们,直到您决定丢弃其余部分。
可选。完成此过程后,每行都有citizenid
,现在可以设置为NOT NULL
,新行必须为citizenid
更多详情: