簡體   English   中英

Oracle - 查找兩個表之間的最佳匹配

[英]Oracle - Find Best Match between Two tables

我和我的團隊很想知道我們可以匹配兩組不同數據的最佳方式。 沒有可以加入的密鑰,因為這些數據來自兩個彼此不了解的獨立來源。 我們將這些數據導入兩個oracle表中,一旦完成,我們就可以開始查找匹配項了。

兩個表都包含一個完整的屬性列表(在房地產中)。 我們需要將Table1中的Properties與Table2中找到的任何可能的匹配屬性進行匹配。 對於Table1中的每個記錄,搜索Table2中的潛在匹配並確定匹配的概率。 我和我的團隊已經決定,最好的方法是比較兩個表中每個表的地址字段。

一個問題是Table1以解析格式提供地址,並將地址編號,地址Street和甚至Address_type分配到單獨的列中,而Table2僅包含一個用於保存地址的列。 每個表都有City,State和Zip列,可以單獨進行比較。

例如 - 見下表1和表2:

請注意,我下面的偽表中的主鍵是與其所在表匹配的Key1和Key2。

    +---------------+---------------+---------------+---------------+---------------+-------+-------+
    +               +    TABLE1     +               +               +               +       +       +
    +---------------+---------------+---------------+---------------+---------------+-------+-------+
    | Key1          | Addr_Number   | Addr_Street   | Addr_Type     | City          | State | Zip   |
    +---------------+---------------+---------------+---------------+---------------+-------+-------+
    | 1001          | 148           | Panas         | Road          | Robinson      | CA    | 76050 |
    | 1005          | 110           | 48th          | Street        | San Juan      | NJ    | 8691  |
    | 1009          | 8571          | Commerce      | Loop          | Vallejo       | UT    | 83651 |
    | 1059          | 714           | Nettleton     | Avenue        | Vista         | TX    | 29671 |
    | 1185          | 1587          | Orchard       | Drive         | Albuquerque   | PA    | 77338 |
    +---------------+---------------+---------------+---------------+---------------+-------+-------+


    +---------------+----------------------+---------------+---------------+---------------+
    +               +    TABLE2            +               +               +               +
    +---------------+----------------------+---------------+---------------+---------------+
    | Key2          | Address              | City          | State         | Zip           |
    +---------------+----------------------+---------------+---------------+---------------+
    | Ax89f         | 148 Panas Road       | Robinson      | CA            | 76050         |
    | B184a         | 110 48th Street      | San Juan      | NJ            | 08691         |
    | B99ff         | 8571 Commerce Lp     | Vallejo       | UT            | 83651         |
    | D81bc         | 714 Nettleton Ave    | Vista         | TX            | 29671         |
    | F84a2         | 1587 Orachard Dr     | Albuquerqu    | PA            | 77338         |
    +---------------+----------------------+---------------+---------------+---------------+

這里的目標是向用戶提供一個輸出,它只顯示Table1中的所有記錄和Table2中找到的最高匹配記錄。 當然可以找到許多可能是匹配的記錄,但我們希望保持這種一對一的關系,而不是在這個初始輸出中產生重復。 輸出應該只是表1中的一個記錄,與表2中的最佳查找匹配。

請參閱下面我嘗試創建的Desired輸出的示例:

    +--------+-------+----------------+---------------------------+
    +        +       + Matched_Output +                           +
    +--------+-------+----------------+---------------------------+
    | Key1   | Key2  |  Percent_Match | num_Matched_Records > 90% |
    +--------+-------+----------------+---------------------------+
    | 1001   | Ax89f |  100%          |  5                        |   --All Parsed Values Match
    | 1005   | B184a |  98%           |  4                        |   --Zip Code prefixed with Zero in Table 2
    | 1009   | B99ff |  95%           |  3                        |   --Loop Vs Lp
    | 1059   | D81bc |  95%           |  2                        |   --Avenue Vs Ave
    | 1185   | F84a2 |  97%           |  2                        |   --City Spelled Wrong in Table 2 and Drive vs Dr
    +--------+-------+----------------+---------------------------+

在輸出中我想看到Table1中的Key1和它旁邊的匹配記錄,表明它與Table2中的記錄匹配到Key2。 接下來我們需要知道這兩個記錄的匹配程度。 表2中可能有許多記錄顯示匹配表1中記錄的概率。 實際上,表2中的每個記錄都可以從0%到100%匹配一直分配一個百分比。

那么現在主要問題是:如何獲得這個百分比?

如何解析Table2中的Address列,以便我可以比較構成Table1中地址的每個列,然后對每個解析的值應用比較算法?

到目前為止,這是我的團隊和我自己提出的(頭腦風暴,Spitballin,無論你想稱之為什么)。

我們已經看了幾個內置的Oracle函數來獲取我們正在尋找的百分比以及嘗試使用正則表達式。 如果我可以點擊谷歌並獲得他們的一些搜索算法,我會。 顯然我沒有那么奢侈,必須自己設計。

regexp_count(table2_city,'(^| )'||REPLACE(table1_city,' ','|')||'($| )') city_score,
regexp_count(table2_city,'(^| )') city_max,

to_char((city_score/city_max)*100, '999G999G999G999G990D00')||'%' city_perc,

以上就是我的團隊和我用來作為概念證明的東西。 我們只是從兩個表中選擇了這些值,並對這些列運行'regexp_count'函數。 以下是我們看過的一些其他功能:

SOUNDEX

REGEXP_LIKE

REGEXP_REPLACE

這些函數很棒,但我不確定它們是否可以在兩個表之間的單個查詢中使用以產生所需的輸出。

另一個想法是我們可以創建一個Function(),它將我們想要用來比較的Address字段作為參數。 然后,該函數將在Table2中搜索最高可能的匹配,並將Table2中的Key2值返回給用戶。

函數(Addr_Number,Addr_Street,Addr_type,City,State)RETURN table2.key2

例如,可能這樣的'可以'工作:

Select tb1.key1, table2Function(tb1.Addr_Number, tb1.Addr_Street, tb1.Addr_type, tb1.City, tb1.State) As Key2
From Table1 tb1;

最后,只知道表1中目前有大約15k記錄,表2中有20k記錄。 同樣......表1中的每條記錄都需要根據表2中的每條記錄進行檢查,以確定是否存在匹配。

我聽見了。 並提前感謝您的反饋。

使用UTL_MATCH包:

Oracle安裝程序

CREATE TABLE Table1 ( Key1, Addr_Number, Addr_Street, Addr_Type, City, State, Zip ) AS
SELECT 1001, 148,  'Panas',     'Road',   'Robinson',    'CA', 76050 FROM DUAL UNION ALL
SELECT 1005, 110,  '48th',      'Street', 'San Juan',    'NJ',  8691 FROM DUAL UNION ALL
SELECT 1009, 8571, 'Commerce',  'Loop',   'Vallejo',     'UT', 83651 FROM DUAL UNION ALL
SELECT 1059, 714,  'Nettleton', 'Avenue', 'Vista',       'TX', 29671 FROM DUAL UNION ALL
SELECT 1185, 1587, 'Orchard',   'Drive',  'Albuquerque', 'PA', 77338 FROM DUAL;


CREATE TABLE Table2 ( Key2, Address, City, State, Zip ) AS
SELECT 'Ax89f', '148 Panas Road',    'Robinson',   'CA', '76050' FROM DUAL UNION ALL
SELECT 'B184a', '110 48th Street',   'San Juan',   'NJ', '08691' FROM DUAL UNION ALL
SELECT 'B99ff', '8571 Commerce Lp',  'Vallejo',    'UT', '83651' FROM DUAL UNION ALL
SELECT 'D81bc', '714 Nettleton Ave', 'Vista',      'TX', '29671' FROM DUAL UNION ALL
SELECT 'F84a2', '1587 Orachard Dr',  'Albuquerqu', 'PA', '77338' FROM DUAL;

查詢

SELECT Key1,
       Key2,
       UTL_MATCH.EDIT_DISTANCE_SIMILARITY(
         A.Addr_Number || ' ' || A.Addr_Street || ' ' || A.Addr_Type
           || ' ' || A.City || ' ' || A.State || ' ' || A.Zip,
         B.Address || ' ' || B.City || ' ' || B.State || ' ' || B.Zip
       ) AS Percent_Match,
       CASE WHEN UTL_MATCH.EDIT_DISTANCE_SIMILARITY(
              A.Addr_Number || ' ' || A.Addr_Street || ' ' || A.Addr_Type,
              B.Address
            ) >= 90
            THEN 1
            ELSE 0
            END
       +
       CASE WHEN UTL_MATCH.EDIT_DISTANCE_SIMILARITY( A.City, B.City ) >= 90
            THEN 1
            ELSE 0
            END
       +
       CASE WHEN UTL_MATCH.EDIT_DISTANCE_SIMILARITY( A.State, B.State ) >= 90
            THEN 1
            ELSE 0
            END
       +
       CASE WHEN UTL_MATCH.EDIT_DISTANCE_SIMILARITY( A.Zip, B.Zip ) >= 90
            THEN 1
            ELSE 0
            END AS Num_Matched
FROM   Table1 A
       INNER JOIN
       Table2 B
       ON ( SYS.UTL_MATCH.EDIT_DISTANCE_SIMILARITY(
              A.Addr_Number || ' ' || A.Addr_Street || ' ' || A.Addr_Type
                || ' ' || A.City || ' ' || A.State || ' ' || A.Zip,
              B.Address || ' ' || B.City || ' ' || B.State || ' ' || B.Zip
            ) > 80 );

輸出

      KEY1 KEY2  PERCENT_MATCH NUM_MATCHED
---------- ----- ------------- -----------
      1001 Ax89f           100           4 
      1005 B184a            97           3 
      1009 B99ff            95           3 
      1059 D81bc            92           3 
      1185 F84a2            88           3 

一些想法。

首先,您可能需要查看utl_match包: https ://docs.oracle.com/cd/E18283_01/appdev.112/e16760/u_match.htm

然后:你肯定會想要通過郵政編碼和州先匹配。 也許在需要的地方添加前導零到郵政編碼 - 雖然顯然你的一個問題是拼寫錯誤,而不僅僅是輸入數據的不同包裝。 如果郵政編碼中存在拼寫錯誤,你可以或多或少地處理它,但如果狀態中的拼寫錯誤真的很糟糕。

您可能希望按城市對相似性進行評分,但這通常無濟於事。 例如,出於所有實際目的,紐約布魯克林應該被視為與紐約紐約市相匹配,但是你無法在你的項目中做到這一點。 因此,我會非常重視城市的匹配。

關於地址類型的類似評論; 也許你可以創建一個具有等價的小表,例如Street,Str,Str。 或Lane,Ln,Ln。 但事實是,當他們給你一個地址時,人們往往不一致; 他們可能會將“幸運街”稱為“Clover Street”,將“Clover Avenue”稱為另一個來源。 因此,最好只比較街道號碼和街道名稱。

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM