合并 Best Key 上的遗留数据

Merging Legacy Data on Best Key

我正在从遗留系统中引入一个字段,该字段与新 table 没有主键-外键关系。数据是事务性的,每行都有一个客户和销售代表。

遗留字段与客户有多对多关系(但仅限于某些),但当您 link 客户和销售代表时,它会变成一对多。但是,数据混乱,交易可能与销售代表不完全匹配。

看来解决这个问题的最好方法是尽可能加入客户和销售代表,如果不匹配,则加入客户。

我能够在 Excel 中使用以下方法做到这一点:

=IFERROR(VLOOKUP(Customer_SalesRep_Combo, DataTable, 3, FALSE),VLOOKUP(Customer,Datatable,3,FALSE))

excel 中的此函数有效,但电子表格太大,容易崩溃,因此我尝试使用 SQL 代码复制此函数。

请注意,旧系统只输出 CSV 文件,所以我将该 CSV 上传到云端,现在我使用 Databricks 将其转换为 Spark 数据帧,因此我可以在其上使用 SQL 逻辑.

最初,我的想法是使用两个条件(匹配我的 80k 中的 50k)行进行左连接,然后使用一个条件进行左连接。然后我会两次引入遗留字段(如果匹配则两次,如果不匹配则一次)。然后,如果没有硬匹配,我将使用 CASE 语句仅引入 "soft match" 。但是,由于多对多关系,我会在左连接上遇到连接重复。由于我还引入了销售数据,因此我不能有任何重复。但是,如果我可以只使用第一个匹配项并抑制任何重复,我将能够忍受一些不准确的情况。

我看过在联接中使用 case 语句的示例,但我不知道在这种情况下如何使用它。如果我不能让它工作,我将求助于迭代数据帧以匹配 Scala 中的逻辑,但我更喜欢 SQL 解决方案。 我的代码如下。真实版本包含更多字段,但这是我在保留基本逻辑的情况下得到的最简单的。

SELECT 
    InnerQry.Customer,
    InnerQry.SalesRep,
    InnerQry.Sales,
    CASE 
        WHEN InnerQry.LegacyFieldHard IS NULL 
           THEN InnerQry.LegacyFieldSoft
        ELSE InnerQry.LegacyFieldHard
    END AS LegacyField
FROM
    (SELECT 
         A.Customer,
         A.SalesRep, 
         A.Sales,
         B.LegacyFieldHard,
         C.LegacyFieldSoft
     FROM 
         DBS AS A
     LEFT JOIN 
         LEGACY AS B ON A.Customer = B.Customer AND A.SalesRep = B.SalesRep
     LEFT JOIN 
         LEGACY AS C ON A.Customer = B.Customer) AS InnerQry

这里的主要问题是,当您仅基于客户(旧版 C)进行映射时,您会得到多行。为避免这种情况,您可以创建一个行号字段并将其限制为 1,前提是您真的不关心该客户记录中的哪些被映射:

SELECT 
    A.Customer,
    A.SalesRep, 
    A.Sales,
    COALESCE(B.LegacyField,C.LegacyField) as LegacyField
FROM DBS AS A
LEFT JOIN LEGACY AS B ON A.Customer=B.Customer AND A.SalesRep=B.SalesRep
LEFT JOIN 
    (select *,
            row_number() Over (partition by Customer order by SalesRep) as rownum1 
    from LEGACY) AS C ON A.Customer=C.Customer and C.rownum1=1

此外,您可以直接使用 COALESCE 函数,而不是 case 语句。这将自动使用第一个非空值。即)仅当 B 为 NULL 时才会采用 C 值。希望这有帮助。