目录

  • 0.引言
  • 1.SCD类型
  • 2.举个栗子
  • 3.SCD2
    • 3.1 什么是SCD2
    • 3.2 如何使用SCD2
    • 3.3 如何实现SCD2
      • 3.3.1 获取维度基准
      • 3.3.2 按情况分治打标
      • 3.3.3更新维度表

0.引言

缓慢变化维技术(Slow Changing Dimension,简称SCD)是维度建模中几乎无时无刻不在使用的技术,它为维度提供了基于历史数据进行切片、切块的能力。

1.SCD类型

以kimball老爷子的理论,共有7种SCD类型,但在日常的数仓开发中,最常使用的是SCD2。所谓SCD2类型,即在维度表中增加新行记录最新维度

2.举个栗子

假设我们有一张地域维度表,记录了行政区号、地名信息。建表语句如下:

--基于HQL方言
CREATE TABLE DIM_ADD(
ADD_NO STRING COMMENT '地域编码',
ADD_NAME STRING COMMENT '地域名称'
)

其中有一行数据:

ADD_NO ADD_NAME
010 北京

我们知道,在100年前,北京还不叫“北京”,叫做“北平”,如果我们要基于100年前的数据进行分析,那彼时的地名字段应写做“北平”。可是我们的维表中没有“北平”,该怎么办呢?

3.SCD2

3.1 什么是SCD2

为了解决第二节的问题,SCD2就是一种非常优雅的办法。

SCD2,Kimball老爷子只总结了两个字——“新增”。

说白了,就是在维度表中保留历史数据新增最新数据,并以数据的生效时间段来约束数据的有效性。

一张简单的SCD2类型维度表建表语句如下:

--基于HQL方言
CREATE TABLE DIM_ADD_SCD2(
ADD_NO STRING COMMENT '地域编码',
ADD_NAME STRING COMMENT '地域名称',
FROM_DATE STRING COMMENT '起始时间',
TO_DATE STRING COMMENT '结束时间'
)

接着,北平的数据就可以维护进来

ADD_NO ADD_NAME FROM_DATE TO_DATE
010 北平 1368-09-12 1947-09-27
010 北京 1947-09-28 9999-12-31

我们可以看到,在SCD2类型中,维护了FROM_DATETO_DATE,代表了起始时间结束时间,业务时间落在其中时就叫生效时间段

注意
1.自然键相同的维度值,各行之起止时间跨度,不得有交集,从业务上讲不合逻辑,同时会导致数据翻倍。
2.最新的数据,结束时间写“9999-12-31”即可。
3.若基于HQL开发,起始时间、结束时间可直接使用STRING类型,与STRING、DATE类型变量都可以直接进行比较。

3.2 如何使用SCD2

在使用SCD2类型的维度表时也非常简单,只需在WHERE条件或JOIN条件中使用业务时间去限制起始时间、结束时间即可。

如现在有一分析需求,欲从户口事实表中计算1942年各个城市登记入籍的人数。

户口事实表建表语句如下:

--基于HQL方言
CREATE TABLE FACT_HOUSEHOLD(
HOUSEHOLD_NO STRING COMMENT '户口编码',
ADD_NO STRING COMMENT '地域编码',
HOUSEHOLD_CNT INT COMMENT '在籍人数',
HOUSEHOLD_RECORD_DATE STRING COMMENT '入籍时间'
)

数据示例:

HOUSEHOLD_NO ADD_NO HOUSEHOLD_CNT HOUSEHOLD_RECORD_DAY
0000000001 010 2 1937-09-27
0000000003 029 3 2013-09-01
0000000004 0533 3 2010-09-01

那么需求指标计算SQL为:

--基于HQL方言
SELECT T2.ADD_NAME AS ADD_NAME,SUM(NVL(T1.HOUSEHOLD_CNT,0)) AS ADD_POPULATIONFROM FACT_HOUSEHOLD T1JOIN DIM_ADD_SCD2 T2ON T1.ADD_NO = T2.ADD_NOAND SUBSTR(T2.TO_DATE,1,4) >= '1942'AND SUBSTR(T2.TO_DATE,1,4) <= '1942'WHERE SUBSTR(HOUSEHOLD_RECORD_DAY,1,4) = '1942';
--一般而言,传参会写占位符基于业务时间生成,此为示例,故写为固定值。

以上便是一个简易的demo,介绍了如何在计算指标时使用SCD2类型维度表。

3.3 如何实现SCD2

仍以3.2节中的DIM_ADD_SCD2为例,要对其进行更新,更新的依据是通过ETL获取的最新地域维度信息表——DIM_ADD_NEW。

其建表语句如下:

--基于HQL方言
CREATE TABLE DIM_ADD_NEW(
ADD_NO STRING COMMENT '地域编码',
ADD_NAME STRING COMMENT '地域名称'
)

设其中数据如下:

ADD_NO ADD_NAME
010 北京
002 A3
003 B1
004 C1

我们对DIM_ADD_NEW中的数据分而治之:

情况一,在自然键对应时,DIM_ADD_NEW中与DIM_ADD_SCD2最新一条数据无差异,则不做操作。

情况二,在自然键对应时,DIM_ADD_NEW中与DIM_ADD_SCD2最新一条数据有差异,则将此自然键DIM_ADD_SCD2中最新一条数据结束时间设置为业务时间(或业务时间-1d,视具体业务而定),并插入最新维度数据,起始时间设置为业务时间+1d(或业务时间,视具体业务而定),结束时间设置为’9999-12-31’。

情况三,之于某自然键,DIM_ADD_NEW中存在而DIM_ADD_SCD2中不存在,新增之,起始时间设置为业务时间+1d(或业务时间,视具体业务而定),结束时间设置为’9999-12-31’。

下面我们以此命题进行一个小demo代码的撰写:

3.3.1 获取维度基准

设维表有数据如下:

ADD_NO ADD_NAME FROM_DATE TO_DATE
010 北平 1368-09-12 1947-09-27
010 北京 1947-09-28 9999-12-31
002 A1 1234-01-01 1949-10-01
002 A2 1949-10-02 9999-12-31
003 B1 1234-01-01 9999-12-31

获取DIM_ADD_SCD2结束日期为9999-12-31的数据作为基准。

--基于HQL方言
CREATE TABLE DIM_ADD_SCD2_NEWEST AS
SELECT T1.ADD_NO,T1.ADD_NAMEFROM DIM_ADD_SCD2 T1WHERE T1.TO_DATE = '9999-12-31';

处理过后数据如下:

ADD_NO ADD_NAME
010 北京
002 A2
003 B1

3.3.2 按情况分治打标

对 3.3 中提到的三种情况,对最新数据进行打标,打标字段命名为FLAG,0对应情况一,1对应情况2,2对应情况三。

建表语句如下:

--基于HQL方言
CREATE TABLE DIM_ADD_NEW_FLAG(
ADD_NO STRING COMMENT '地域编码',
ADD_NAME STRING COMMENT '地域名称',
FLAG STRING COMMENT '情况标识'
)

对应情况一,有代码:

--基于HQL方言
INSERT INTO TABLE DIM_ADD_NEW_FLAG
SELECT T1.ADD_NO AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,'1' AS FLAGFROM DIM_ADD_NEW T1JOIN DIM_ADD_SCD2_NEWEST T2 --JOIN起过滤作用ON T1.ADD_NO = T2.ADD_NO AND T1.ADD_NAME = T2.ADD_NAME ;

对应情况二,有代码:

--基于HQL方言
INSERT INTO TABLE DIM_ADD_NEW_FLAG
SELECT T1.ADD_NO AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,'2' AS FLAGFROM DIM_ADD_NEWT1LEFT JOIN DIM_ADD_SCD2_NEWEST T2ON T1.ADD_NO = T2.ADD_NO AND T1.ADD_NAME = T2.ADD_NAME WHERE T2.ADD_NO IS NULL --关联不上,代表有更新数据AND T1.ADD_NO  IN (SELECT ADD_NO  FROM OLD_NEWEST) --自然键需重合;

对应情况三,有代码:

--基于HQL方言
INSERT INTO TABLE DIM_ADD_NEW_FLAG
SELECT T1.ADD_NO AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,'3' AS FLAGFROM DIM_ADD_NEW T1LEFT JOIN DIM_ADD_SCD2_NEWEST T2ON T1.ADD_NO = T2.ADD_NO AND T1.ADD_NAME = T2.ADD_NAME WHERE T2.ADD_NO IS NULL --关联不上,代表是新数据AND T1.ADD_NO  NOT IN (SELECT ADD_NO  FROM OLD_NEWEST) --自然键需不对称;

则此时,DIM_ADD_NEW_FLAG有数据:

ADD_NO ADD_NAME FLAG
010 北京 1
002 A3 2
003 B1 1
004 C1 3

3.3.3更新维度表

本demo基于HQL方言,故无法进行UPDATE操作,在更新时需使用如下代码:

首先,生成一个临时表,作为处理结果的载体,并以此更新维度表,建表语句与DIM_ADD_SCD2相同:

--基于HQL方言
CREATE TABLE DIM_ADD_SCD2_TMP(
ADD_NO STRING COMMENT '地域编码',
ADD_NAME STRING COMMENT '地域名称',
FROM_DATE STRING COMMENT '起始时间',
TO_DATE STRING COMMENT '结束时间'
)

对于情况1,使用自然键将DIM_ADD_SCD2 与DIM_ADD_NEW_FLAG关联,原样装载至临时表即可 :

--基于HQL方言
INSERT INTO TABLE DIM_ADD_SCD2_TMP
SELECT T1.ADD_NO AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,T1.FROM_DATE AS FROM_DATE ,T1.TO_DATE AS TO_DATE FROM DIM_ADD_SCD2 T1JOIN DIM_ADD_NEW_FLAG T2ON T1.ADD_NO  = T2.ADD_NO AND T2.FLAG = '1';

对于情况二,我们需要将原维度表非最新数据原样装载。最新一条数据的结束时间设为业务时间。并基于DIM_ADD_NEW_FLAG新增一条数据,开始时间为业务时间+1d,结束时间为‘9999-12-31’。

--基于HQL方言
--原样装载非最新数据
INSERT INTO TABLE DIM_ADD_SCD2_TMP
SELECT T1.ADD_NO AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,T1.FROM_DATE AS FROM_DATE ,T1.TO_DATE AS TO_DATE FROM DIM_ADD_SCD2 T1JOIN DIM_ADD_NEW_FLAG T2ON T1.ADD_NO  = T2.ADD_NO AND T2.FLAG = '2'
WHERE T1.TO_DATE != '9999-12-31'UNION ALL--将最新一条数据至结束时间设置为业务时间
SELECT T1.ADD_NO  AS ADD_NO ,T1.ADD_NAME AS ADD_NAME ,T1.FROM_DATE AS FROM_DATE ,'${business_tm}'  AS TO_DATE --一般而言会传入一个业务时间,此处用占位符表示FROM DIM_ADD_SCD2 T1JOIN DIM_ADD_NEW_FLAG T2ON T1.ADD_NO  = T2.ADD_NO AND T2.FLAG = '2'
WHERE T1.TO_DATE = '9999-12-31' UNION ALL--插入最新维度值
SELECT ADD_NO  AS ADD_NO ,ADD_NAME AS ADD_NAME ,DATE_ADD('${business_tm}',1) AS FROM_DATE ,'9999-12-31' AS TO_DATEFROM DIM_ADD_NEW_FLAG
WHERE FLAG = '2' ;

对于情况三,将新数据装载至维度表即可,有代码如下:

--基于HQL方言
INSERT INTO TABLE DIM_ADD_SCD2_TMP
SELECT ADD_NO  AS ADD_NO ,ADD_NAME AS ADD_NAME ,DATE_ADD('${business_tm}',1) AS FROM_DATE ,'9999-12-31' AS TO_DATEFROM DIM_ADD_NEW_FLAG
WHERE FLAG = '3'

最后,我们将临时表的数据覆写至维度表。

--基于HQL方言
INSERT OVERWRITE TABLE DIM_ADD_SCD2
SELECT ADD_NO  AS ADD_NO ,ADD_NAME AS ADD_NAME ,'${business_tm}' AS FROM_DATE ,‘9999-12-31’ AS TO_DATEFROM DIM_ADD_SCD2_TMP

新维表中数据如下:

ADD_NO ADD_NAME FROM_DATE TO_DATE
010 北平 1368-09-12 1947-09-27
010 北京 1947-09-28 9999-12-31
002 A1 1234-01-01 1949-10-01
002 A2 1949-10-02 2021-11-20
002 A3 2021-11-21 9999-12-31
003 B1 1234-01-01 9999-12-31
004 C1 2021-11-20 9999-12-31

至此,一轮SCD2类型的维表更新完毕。


以上就是本章内容,相信大家已经对SCD2类型是什么,如何使用,如何搭建有了清晰的认识。

下一章讲解蜈蚣事实表的归约优化,敬请期待。

【版权所有,翻版必究。】

吴乙己的数仓指南_5.1维度建模技巧之SCD2类型缓慢变化维搭建相关推荐

  1. 吴乙己的数仓指南_2维度建模核心思想

    目录 0.引言 1.维度建模"四部曲" 1.1选择业务过程 1.2声明粒度 1.3确定维度 1.4确定事实 2.总线矩阵 0.引言 前两章讲了很多宽泛,大而全,代码之外的东西,想必 ...

  2. 数仓缓慢变化维SCD深度讲解

    维度缓慢变化维SCD(Slowly Changing Dimensions)一些维度表的数据不是静态的,而是会随着时间而缓慢地变化(这里的缓慢是相对事实表而言,事实表数据变化的速度比维度表快,如果还不 ...

  3. 数据中台 第7章 数据体系建设:数仓分层设计、数据建模

    数据中台数据体系是在全域原始数据的基础上,进行标准定义及分层建模,数据体系建设最终呈现的结果是一套完整.规范.准确的数据体系,可以方便支撑数据应用. 中台数据体系应具备以下特征: ·覆盖全域数据:数据 ...

  4. 数仓(二)关系建模和维度建模

    上一篇我们了解了OLTP和OLAP数据处理类型.OLTP处理的是关系模型表即实体-关系表ER,而OLAP处理的是维度模型表. 数仓(一)简介数仓,OLTP和OLAP 本篇我们来讨论一下数仓中两种建模的 ...

  5. ☀️ 数仓建模理论,大数据邻域通用的维度建模技巧【建议收藏学习】

    文章目录 前言: 正文: 关系建模 关系建模的特点 维度建模 维度建模的特点 事实表 维度模型的分类 各模型的适用场景 建模阶段具体的划分 1. ODS层 ( 原始数据存储层,直接加载原始日志.数据保 ...

  6. 数据仓库灵魂30问之数仓有哪几种建模思想?

    范式建模 范式建模在实际的应用中有:第一范式(1NF).第二范式(2NF).第三范式(3NF).巴斯-科德范式(BCNF).第四范式(4NF).第五范式(5NF) 在企业范式建模中,一般追求三范式,即 ...

  7. 数据仓库知识点总结(数仓分层建模、维度建模等)

    数据仓库知识点总结 推荐学习<华为数据之道><数据仓库工具箱-维度建模权威指南>两本书. 此文档是数据仓库建模的知识点总结文档,在持续更新中(2021-10-13). 文章目录 ...

  8. 数仓建设(离线和实时)

    文档大纲: 一.数仓基本概念 1. 数据仓库架构 我们在谈数仓之前,为了让大家有直观的认识,先来谈数仓架构,"架构"是什么?这个问题从来就没有一个准确的答案.这里我们引用一段话:在 ...

  9. 一文读懂数仓建设和数据治理

    点击上方 "大数据肌肉猿"关注, 星标一起成长 点击下方链接,进入高质量学习交流群 今日更新| 950个转型案例分享-大数据交流群 本文分为两大节介绍,第一节是数仓建设,第二节是数 ...

最新文章

  1. hibernate查询之条件查询
  2. CSS设置图片的重复
  3. Jerry本地安装SAP Kyma的一些失败尝试
  4. 适合新手使用的编辑制作管理软件:Substance Alchemist Mac版
  5. linux ls命令无法执行,更新了个依赖程序,结果悲剧了,连ls命令都不能用,大神帮帮忙!...
  6. Spring注入静态类型
  7. 2018 Multi-University Training Contest 7 - GuGuFishtion
  8. 【2019数学建模】国赛C题:机场出租车优化问题(原创)
  9. Python爬虫实现英汉互译
  10. WordPress简约mkBlog博客主题模板v2.1
  11. 洛谷3678:简单的数学题(画柿子+杜教筛)
  12. 修改系统默认 alert 弹框样式
  13. 借助云开发实现小程序朋友圈的发布与展示
  14. python爬虫学习笔记 3.9 (了解参考:训练Tesseract)
  15. redies 须知小结
  16. python股票数据分析_用Python抓取新浪的股票数据
  17. 坏男人是丈夫的最佳人选
  18. 固定于计算机主机箱中承载,计算机主机完整
  19. 关于vue+elementui设置div背景图片填充不生效问题
  20. 易语言lsp劫持_易语言网截插件修复源码

热门文章

  1. 【华为OD统一考试B卷 | 200分】宜居星球改造计划(Java JavaScript Python)
  2. 简述ip地址的abc类如何划分_IP地址如何分类 ?ABC类IP是怎么划分的?
  3. mac中sublime替换回车键
  4. identity的作用
  5. 安卓Android Studio布局文件分类存放,java文件分类存放
  6. gm工具怎样连接mysql_Gm工具2.0连接不上,求助
  7. startsWith
  8. Android5.1 Art Hook 技术分享
  9. 如何安装STM32CubeMX
  10. 0018__九针串口公母头定义 RS232串口线常见接法与引脚定义