2015-07-01 134 views
0

我有兩個表,已經填充了數據如下:Postgres的查詢交叉檢查2個表

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(​​)。

現在我需要每一行table2獲得citizenid,從table1相關聯,因此,在年底,我得到table2額外的ID列,正確地與每個人相關。

喜歡的東西在table1一個人(在table2行),其中某些條件下比賽,如果在table1存在的紀錄,把該記錄的ID列在table2搜索。

但是快速和所有的行。
table1的行數約爲200萬。
表2的行數大約爲900.000

+0

計算機c應該非常有效地解決這個問題。基本上你不能加入這些表格。也許你可以創建第三個表,將這兩個錶鏈接在一起,或者將一個表中的列添加到另一個表中。 – Jasen

+0

你忘了提供數據類型和約束。用'\ d tbl'提供你從psql得到的東西(的相關部分)。而且,作爲* always *,你的Postgres版本。另外,雙方都可以有重複嗎? –

+0

vresion 9.1 表1: uniqid:整數(11位),PK 名:字符,不爲空 出生日期:日期,不爲空 地址:字符,不爲空 表2: 姓名,地址,性別,insutype: char,not null birthdate:date,not null table1數據來自民事登記處。這是參考。沒有重複。 表2數據是建議的醫療保健接受者名單,由領域官員手動收集(不幸的是,不包括公民身份證號碼),然後應該提交給每個人都有公民身份證的部門。 所以我需要在table2中的每個人上輸入正確的公民ID,使用table1作爲參考 – rifaiz

回答

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. 更新表2中的所有行,使用完美匹配。也立即在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

  • 更多詳細信息:

    +0

    非常感謝Erwin,儘管在CTE上還是相對新手。 我可以看到方向。 – rifaiz

    +0

    @rifaiz:[搜索\ [postgres \]數據修改CTE](http://stackoverflow.com/search?q= [postgres] +數據修改+ CTE),你會發現很多例子和解釋。我還添加了一個鏈接到上面的手冊。 –