Слияние устаревших данных на Best Key - PullRequest
0 голосов
/ 31 января 2020

Я ввожу поле из прежней системы, которая не имеет отношения Первичный ключ-Внешний ключ с новой таблицей. Данные являются транзакционными, и в каждой строке есть клиент и торговый представитель.

Унаследованное поле имеет много-много-многократные отношения с клиентом (но только у некоторых), но оно связывает одного со многими, когда вы связываете клиента и торгового представителя. Однако данные являются беспорядочными, и транзакция может не соответствовать торговому представителю.

Похоже, что лучший способ решить эту проблему - присоединиться к клиенту и торговому представителю, если это возможно, если нет совпадения, тогда просто присоединиться к клиенту.

Мне удалось сделать это в Excel с помощью следующего:

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

Эта функция в Excel работает, но электронная таблица настолько велика, что имеет тенденцию создавать sh, поэтому Я пытаюсь продублировать это, используя SQL код.

Обратите внимание, что унаследованная система просто выводит файлы CSV, поэтому я загрузил этот CSV в облако, и теперь я использую блоки данных, чтобы преобразовать их в фрейм данных Spark, чтобы я мог использовать SQL logi c в теме.

Первоначально моя идея состояла в том, чтобы выполнить левое соединение, используя оба условия (что соответствует 50k из моих 80k) строк, и выполнить левое соединение, используя одно условие. Затем я бы привел в поле унаследованных дважды (дважды, если соответствует, один раз, если нет). Тогда я использовал бы оператор CASE, чтобы ввести «мягкое совпадение», только если не было жесткого совпадения. Однако из-за отношений «многие ко многим» у меня возникнет дублирование в левом соединении. Поскольку я также ввожу данные о продажах, у меня не может быть никакого дублирования. Тем не менее, я мог бы жить с некоторой неточностью, если бы я мог просто использовать первое совпадение и подавить любое дублирование.

Я видел примеры использования операторов case в соединениях, но я не знаю, как использовать это в этом случае. Если я не могу заставить это работать, я прибегну к итерации по фреймам данных, чтобы соответствовать логике c в Scala, но я бы предпочел решение SQL. Мой код ниже. Реальная версия содержит больше полей, но это самое простое, что я могу получить, сохранив базовый код c logi c.

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

1 Ответ

1 голос
/ 31 января 2020

Основная проблема здесь заключается в том, что вы получаете несколько строк при отображении только на основе Customer (Legacy 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, вместо описания дела. Это будет автоматически использовать первое ненулевое значение. т.е.) C значение будет приниматься только когда B равно NULL. Надеюсь, это поможет.

...