Postgres查询交叉检查2个表

时间:2015-07-01 04:52:50

标签: sql postgresql pattern-matching similarity

我有两个表,已经填充了如下数据:

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

1 个答案:

答案 0 :(得分:0)

我假设你是唯一一个写表的人,所以没有并发冲突......

  1. 将ID列添加到table2,现在可以为NULL:

    ALTER TABLE table2 ADD COLUMN citizenid int; -- or whatever the type is
    

    考虑在table1上添加一个标记,以便在市场上排除""另一方面也很便宜:

    ALTER TABLE table1 ADD COLUMN hasmatch boolean;
    
  2. 假设两边都没有重复。否则你需要做更多。

  3. 使用完美匹配更新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;
    
  4. 只要一行有citizenid它就会离开市场"在双方。

    1. 检查剩余行数并开始软化婴儿步骤中的谓词,以便始终首先尝试更可能的匹配来防止误报。在开始循环过程之前,请考虑系统策略。分析剩下的行以找到系统的拼写错误或类似的线索。
    2. 字符类型列的模糊匹配的可能选项是:

      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);
      
      1. 一小部分将无法解决。您可以花费越来越多的时间手动分配它们,直到您决定丢弃其余部分。

      2. 可选。完成此过程后,每行都有citizenid,现在可以设置为NOT NULL,新行必须为citizenid

      3. 更多详情: