• (二)ODS层更新:源表和目标表,没有last_update,比对取增量,却重复抽到某部分数据,怎么解决?


    此文转载自:https://blog.csdn.net/u014337370/article/details/110258284#commentBox

    在这里插入图片描述

    源表和目标表,比对的时候,某部分数据,每次比对都被认为是“新数据”,然后每次抽取比对都会被过滤到目标表,从而造成目标表有很多重复数据,是什么原因呢?原因是该表的多个字段“数据缺失严重”,我们比对数据前是已经给空值/空格填了默认值,也就是说这些被填充过的字段,是有很多重复值的。我们联表查询时,关联字段时有重复值时,那这次查询肯定会发散,而我们用的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
      在这里插入图片描述
       

    更多内容详见微信公众号:Python测试和开发

    Python测试和开发

  • 相关阅读:
    SpringBoot上传图片
    Java工具类(4) ------>运用easyexcel生成Excel表格
    SpringBoot(8) ------>集成SpringSecurity与Jwt
    docker_进阶
    jenkins基础
    C# 8 using declarations
    Sysmetric encryption and decryption via AES
    C# class implementation order of constructors include static constructor,constructor without modifiers and parameters, constructor with modifiers and parameters
    C# dictionary keys case insensitive
    Centos7安装Docker及运行hello-world
  • 原文地址:https://www.cnblogs.com/phyger/p/14061026.html
Copyright © 2020-2023  润新知