(二)ODS層更新:源表和目標表,沒有last_update,比對取增量,卻重複抽到某部分數據,怎麼解決?

在這裏插入圖片描述

源表和目標表,比對的時候,某部分數據,每次比對都被認爲是“新數據”,然後每次抽取比對都會被過濾到目標表,從而造成目標表有很多重複數據,是什麼原因呢?原因是該表的多個字段“數據缺失嚴重”,我們比對數據前是已經給空值/空格填了默認值,也就是說這些被填充過的字段,是有很多重複值的。我們聯表查詢時,關聯字段時有重複值時,那這次查詢肯定會發散,而我們用的kettle【合併記錄】插件的原理也是聯表查詢。
我的上一篇文章《ODS層更新:如果源數據沒有“更新時間“字段,如何作增量抽取?我都踩過這些坑》提到用來聯表的字段,一定是該條的數據的唯一標識。如果不是的話,那就造一個,多個字段作爲“關聯字段”避免發散。如果一條數據,10個字段,7個字段缺失,你怎麼造“唯一標識”,最後聯表比對時,還是會發散。也就是說,聯表時,某部分數據字段值缺失嚴重,多對多聯表是有風險的,那有沒有其他取增量更優的解決方案呢?
即然多對多聯表有風險,那就一對一聯表,不就解決了嗎?

  • 取增量思路:源表 left outer join 目標表
    源表
    LEFT OUTER JOIN
    目標表
    WHERE 目標表.關聯字段 IS NULL



  • 建【源表】
 CREATE TABLE work_exper(
id NUMBER(10),
name VARCHAR2(10),
company VARCHAR2(10),
job VARCHAR2(10),
work_start_date date,
work_end_date date
);
  • 給【源表】插入數據
INSERT INTO work_exper VALUES(1001,'喪彪','百度','清潔工',to_date('1997-05-17','yyyy-mm-dd'),to_date('1998-08-15','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1001,'喪彪','騰訊','保安',to_date('1998-09-17','yyyy-mm-dd'),to_date('1999-12-15','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1001,'喪彪','阿里','炊事員',to_date('2000-07-17','yyyy-mm-dd'),to_date('2002-03-18','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1002,'段坤','快手','運營專員',to_date('1996-08-27','yyyy-mm-dd'),to_date('1998-02-08','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1002,'段坤','抖音','主播',to_date('1997-01-17','yyyy-mm-dd'),to_date('1998-02-14','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1002,'段坤','愛奇藝','COO',to_date('1999-05-19','yyyy-mm-dd'),to_date('2008-08-15','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1003,'阿祖','建行','催收員',to_date('2001-05-17','yyyy-mm-dd'),to_date('2018-04-12','yyyy-mm-dd'));
INSERT INTO work_exper VALUES(1001,'喪彪','阿里','炊事班長',to_date('2003-07-17','yyyy-mm-dd'),to_date('2020-03-18','yyyy-mm-dd'));
  • 查詢【源表】:
SELECT 
    id
   ,name
   ,job
   ,work_start_date
   ,work_end_date
FROM 
   work_exper

在這裏插入圖片描述
從上面的源表來看,字段ID+NAME+COMPANY+JOB就可以確定爲該行數據的唯一標識了,但這是“多對多聯表”,現實的業務場景,數據可不是那麼規整的,一定是有很多缺失值的,所以我們如何作“一對一聯表”呢?

  • 用窗口函數row_number()over()給源數據造一個唯一標識
    一個員工只有一個ID,但有多條工作記錄,那我們可以以“ID"進行分組,在組內進行排序,最終將ID+排序結果,這樣便可以得到"唯一標識"
SELECT 
     id||'_'||row_number()over(partition by id order by company,job,work_start_date,work_end_date) as pk_id 
    ,id
    ,name
    ,job
    ,work_start_date
    ,work_end_date
FROM 
    work_exper

在這裏插入圖片描述
接下來建ods層目標表

  • 建ods層【目標表】
CREATE TABLE ods_work_exper(
pk_id VARCHAR2(10),
id NUMBER(10),
name VARCHAR2(10),
company VARCHAR2(10),
job VARCHAR2(10),
work_start_date date,
work_end_date date
);

你可以看出,我並沒有給字段pk_id建立“唯一主鍵約束”,也就是說我允許目標中出現重複的ods_pk_id。爲什麼這樣做呢?因爲id分組組內排序是動態的,難免會出現有一天新數據的pk_id 和某條舊數據的pk_id一樣,但其他字段不一樣的。所以我們取增量的腳本可以改進成。

  • 取增量思路改進:
    源表
    LEFT OUTER JOIN
    目標表
    WHERE 目標表.關聯字段 IS NULL
    OR 源表.字段 <>目標表字段.字段




  • 腳本實例:

SELECT
     A.pk_id 
    ,A.id
    ,A.name
    ,A.company
    ,A.job
    ,A.work_start_date
    ,A.work_end_date
FROM
(
    SELECT
        id||'_'||row_number()over(partition by id order by company,job,work_start_date,work_end_date) as pk_id 
        , id
        , name
        , company
        , job
        , work_start_date
        , work_end_date
    FROM
        work_exper
)  A --源表
LEFT OUTER JOIN
    ods_work_exper B --目標表
ON A.pk_id = B.pk_id 
WHERE B.pk_id IS NULL
    OR A.name <> B.name
    OR A.company <> B.company
    OR A.job <> B.job
    OR A.work_start_date <> B.work_start_date
    OR A.work_end_date <> B.work_end_date

實際的業務場景中,源表和目標表都是來自不同的數據庫。如果源數據庫沒有賦權的情況下,異構數據聯表查詢是實現不了的。我們可以藉助kettle的【記錄集連接】插件
(流程概覽)
在這裏插入圖片描述

  • 1.1 源表:work_exper

在這裏插入圖片描述

  • 1.2目標表:ods_work_exper
    在這裏插入圖片描述
  • 2.記錄集連接
    在這裏插入圖片描述
  • 3.過濾記錄

在這裏插入圖片描述

  • 4.獲取系統信息
    在這裏插入圖片描述
  • 5.新增數據插入目標表:ods_work_exper
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章