【工作杂谈_20260817】多维分析与数据建模: 维度上卷:从明细粒度到汇总层级

文章目录

  • [1. 什么是"维度上卷"](#1. 什么是“维度上卷”)
  • [2. ETL 中上卷的核心是"改变事实粒度"](#2. ETL 中上卷的核心是“改变事实粒度”)
  • [3. ETL 中上卷的完整流程](#3. ETL 中上卷的完整流程)
    • [3.1 数据质量检查](#3.1 数据质量检查)
    • [3.2 加载维表](#3.2 加载维表)
      • [地域维表 DimGeography](#地域维表 DimGeography)
      • [日期维表 DimDate](#日期维表 DimDate)
      • [产品表 DimProduct](#产品表 DimProduct)
    • [3.3 生成明细事实表](#3.3 生成明细事实表)
    • [3.4 预聚合上卷](#3.4 预聚合上卷)
      • [上卷一:Date → Month](#上卷一:Date → Month)
      • [上卷二:City → Province](#上卷二:City → Province)
      • [上卷三:Province → Country](#上卷三:Province → Country)
    • [3.5 一致性校验](#3.5 一致性校验)

我的网站原文: https://eleanora-lyh.github.io/MyLearningNotes/
csdn处的文章会尽快同步更新,欢迎大家来访问!

1. 什么是"维度上卷"

维度上卷 Roll-up 本质上是维度建模和 OLAP 中的分析概念;ETL 中的维度上卷,是通过数据转换和聚合,将细粒度事实数据加工为更高层级、更粗粒度的汇总数据。

  • Roll-up 是分析语义
  • ETL 是实现手段
  • 聚合表、汇总事实表是落地结果

所谓上卷,就是从更细维度层级聚合成更高维度层,例如:

  • 时间维度:日 → 月 → 季度 → 年

  • 地域维度:城市 → 省份 → 国家

  • 产品维度:SKU → SubCategory → Category

例如原始数据是:

Date City Province Country Product Revenue
2026-08-01 City1 Province1 Country1 A 100
2026-08-02 City3 Province2 Country1 A 150
2026-08-01 City2 Province1 Country1 A 80

经过时间和地域上卷(C1/C2都属于P1):

Month Province Product Revenue
2026-08 Province1 A 180
2026-08 Province12 A 150

这里发生了两个变化:

  1. Date → Month
  2. City → Province

同时:Revenue = SUM(100 + 150 + 80) = 330

2. ETL 中上卷的核心是"改变事实粒度"

上卷不能只理解为 GROUP BY

它真正改变的是:

事实表中一行数据所代表的业务范围。

例如:

状态 一行含义 粒度
上卷前 某一天 + 某城市 + 某SKU 的销售情况 Date + City + SKU
上卷后 某个月 + 某省份 + 某产品类别的销售情况 Month + Province + Category

事实表中的维度键决定事实数据的粒度。事实可以存储在更高粒度,但高粒度事实通常无法再准确拆分回更细粒度

即 日级 → 月级 通常是可完成的;

但 月级 → 日级 如果没有保留日级明细,无法准确恢复。

3. ETL 中上卷的完整流程

#mermaid-svg-C5LBh4Nftdx0r9Sj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-C5LBh4Nftdx0r9Sj .error-icon{fill:#552222;}#mermaid-svg-C5LBh4Nftdx0r9Sj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-C5LBh4Nftdx0r9Sj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .marker.cross{stroke:#333333;}#mermaid-svg-C5LBh4Nftdx0r9Sj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-C5LBh4Nftdx0r9Sj p{margin:0;}#mermaid-svg-C5LBh4Nftdx0r9Sj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster-label text{fill:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster-label span{color:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster-label span p{background-color:transparent;}#mermaid-svg-C5LBh4Nftdx0r9Sj .label text,#mermaid-svg-C5LBh4Nftdx0r9Sj span{fill:#333;color:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .node rect,#mermaid-svg-C5LBh4Nftdx0r9Sj .node circle,#mermaid-svg-C5LBh4Nftdx0r9Sj .node ellipse,#mermaid-svg-C5LBh4Nftdx0r9Sj .node polygon,#mermaid-svg-C5LBh4Nftdx0r9Sj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .rough-node .label text,#mermaid-svg-C5LBh4Nftdx0r9Sj .node .label text,#mermaid-svg-C5LBh4Nftdx0r9Sj .image-shape .label,#mermaid-svg-C5LBh4Nftdx0r9Sj .icon-shape .label{text-anchor:middle;}#mermaid-svg-C5LBh4Nftdx0r9Sj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .rough-node .label,#mermaid-svg-C5LBh4Nftdx0r9Sj .node .label,#mermaid-svg-C5LBh4Nftdx0r9Sj .image-shape .label,#mermaid-svg-C5LBh4Nftdx0r9Sj .icon-shape .label{text-align:center;}#mermaid-svg-C5LBh4Nftdx0r9Sj .node.clickable{cursor:pointer;}#mermaid-svg-C5LBh4Nftdx0r9Sj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .arrowheadPath{fill:#333333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C5LBh4Nftdx0r9Sj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-C5LBh4Nftdx0r9Sj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C5LBh4Nftdx0r9Sj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster text{fill:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj .cluster span{color:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-C5LBh4Nftdx0r9Sj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-C5LBh4Nftdx0r9Sj rect.text{fill:none;stroke-width:0;}#mermaid-svg-C5LBh4Nftdx0r9Sj .icon-shape,#mermaid-svg-C5LBh4Nftdx0r9Sj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C5LBh4Nftdx0r9Sj .icon-shape p,#mermaid-svg-C5LBh4Nftdx0r9Sj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-C5LBh4Nftdx0r9Sj .icon-shape .label rect,#mermaid-svg-C5LBh4Nftdx0r9Sj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C5LBh4Nftdx0r9Sj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-C5LBh4Nftdx0r9Sj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-C5LBh4Nftdx0r9Sj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-C5LBh4Nftdx0r9Sj .step>*{fill:#FFE08A!important;stroke:#A86700!important;color:#3D2900!important;stroke-width:2px!important;}#mermaid-svg-C5LBh4Nftdx0r9Sj .step span{fill:#FFE08A!important;stroke:#A86700!important;color:#3D2900!important;stroke-width:2px!important;}#mermaid-svg-C5LBh4Nftdx0r9Sj .step tspan{fill:#3D2900!important;} 原始数据
Step1: 数据质量检查
检查 City → Province 是否唯一
检查 Province → Country 是否唯一
识别缺失、错误和历史变更
Step2: 加载维表
DimDate
DimGeography
DimProduct
Step3: 生成明细事实表
FactRevenueDaily
Step4: 预聚合上卷
FactRevenueMonthlyCity
FactRevenueMonthlyProvince
FactRevenueMonthlyCountry
Step5: 一致性校验
各级 Revenue 总和均应为 330

3.1 数据质量检查

检查 City → Province

City Province 是否唯一
City1 Province1
City2 Province1
City3 Province2

当前数据中,每个 City 只属于一个 Province,因此层级关系正常。

检查 Province → Country

Province Country 是否唯一
Province1 Country1
Province2 Country1

最终可以建立稳定的地理层级:
#mermaid-svg-DcpqhTOEfwKWftYL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DcpqhTOEfwKWftYL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DcpqhTOEfwKWftYL .error-icon{fill:#552222;}#mermaid-svg-DcpqhTOEfwKWftYL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DcpqhTOEfwKWftYL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DcpqhTOEfwKWftYL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DcpqhTOEfwKWftYL .marker.cross{stroke:#333333;}#mermaid-svg-DcpqhTOEfwKWftYL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DcpqhTOEfwKWftYL p{margin:0;}#mermaid-svg-DcpqhTOEfwKWftYL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DcpqhTOEfwKWftYL .cluster-label text{fill:#333;}#mermaid-svg-DcpqhTOEfwKWftYL .cluster-label span{color:#333;}#mermaid-svg-DcpqhTOEfwKWftYL .cluster-label span p{background-color:transparent;}#mermaid-svg-DcpqhTOEfwKWftYL .label text,#mermaid-svg-DcpqhTOEfwKWftYL span{fill:#333;color:#333;}#mermaid-svg-DcpqhTOEfwKWftYL .node rect,#mermaid-svg-DcpqhTOEfwKWftYL .node circle,#mermaid-svg-DcpqhTOEfwKWftYL .node ellipse,#mermaid-svg-DcpqhTOEfwKWftYL .node polygon,#mermaid-svg-DcpqhTOEfwKWftYL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DcpqhTOEfwKWftYL .rough-node .label text,#mermaid-svg-DcpqhTOEfwKWftYL .node .label text,#mermaid-svg-DcpqhTOEfwKWftYL .image-shape .label,#mermaid-svg-DcpqhTOEfwKWftYL .icon-shape .label{text-anchor:middle;}#mermaid-svg-DcpqhTOEfwKWftYL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DcpqhTOEfwKWftYL .rough-node .label,#mermaid-svg-DcpqhTOEfwKWftYL .node .label,#mermaid-svg-DcpqhTOEfwKWftYL .image-shape .label,#mermaid-svg-DcpqhTOEfwKWftYL .icon-shape .label{text-align:center;}#mermaid-svg-DcpqhTOEfwKWftYL .node.clickable{cursor:pointer;}#mermaid-svg-DcpqhTOEfwKWftYL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DcpqhTOEfwKWftYL .arrowheadPath{fill:#333333;}#mermaid-svg-DcpqhTOEfwKWftYL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DcpqhTOEfwKWftYL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DcpqhTOEfwKWftYL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DcpqhTOEfwKWftYL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DcpqhTOEfwKWftYL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DcpqhTOEfwKWftYL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DcpqhTOEfwKWftYL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DcpqhTOEfwKWftYL .cluster text{fill:#333;}#mermaid-svg-DcpqhTOEfwKWftYL .cluster span{color:#333;}#mermaid-svg-DcpqhTOEfwKWftYL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DcpqhTOEfwKWftYL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DcpqhTOEfwKWftYL rect.text{fill:none;stroke-width:0;}#mermaid-svg-DcpqhTOEfwKWftYL .icon-shape,#mermaid-svg-DcpqhTOEfwKWftYL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DcpqhTOEfwKWftYL .icon-shape p,#mermaid-svg-DcpqhTOEfwKWftYL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DcpqhTOEfwKWftYL .icon-shape .label rect,#mermaid-svg-DcpqhTOEfwKWftYL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DcpqhTOEfwKWftYL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DcpqhTOEfwKWftYL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DcpqhTOEfwKWftYL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} City1
Province1
City2
City3
Province2
Country1

3.2 加载维表

不建议在事实表里重复保存 City、Province、Country 名称。所以按照星型模型可以拆分事实数据与维度数据

  • 地域维表 DimGeography

  • 日期维表 DimDate

  • 产品表 DimProduct

地域维表 DimGeography

GeographyKey City Province Country
101 City1 Province1 Country1
102 City3 Province2 Country2
103 City2 Province1 Country1

日期维表 DimDate

DateKey Date Month Quarter Year
20260801 2026-08-01 2026-08 2026-Q3 2026
20260802 2026-08-02 2026-08 2026-Q3 2026

产品表 DimProduct

ProductKey Product
201 A

如果存在产品类别,还可以设计为:Product → ProductCategory → ProductLine

3.3 生成明细事实表

  • 明细事实表FactRevenueDaily
DateKey GeographyKey ProductKey Revenue
20260801 101 201 100
20260802 103 201 150
20260801 102 201 80

粒度仍然是:Date + GeographyKey + Product

City、Province、Country 名称不需要重复保存在事实表中,而是通过 GeographyKey 关联 DimGeography

3.4 预聚合上卷

上卷一:Date → Month

目标粒度:Month + City + Product,生成 FactRevenueMonthlyCity

Month City Product Revenue
2026-08 City1 A 100
2026-08 City2 A 80
2026-08 City3 A 150

这里只提升了时间层级:Date → Month

City 维度仍保留在原层级


上卷二:City → Province

目标粒度:Month + Province + Product,生成 FactRevenueMonthlyProvince

Month Province Product Revenue
2026-08 Province1 A 180
2026-08 Province2 A 150

计算过程:

plain 复制代码
Province1 = City1 100 + City2 80 = 180
Province2 = City3 150

这里同时发生:

Date → Month

City → Province


上卷三:Province → Country

目标粒度:Month + Country + Product,生成 FactRevenueMonthlyCountry

Month Country Product Revenue
2026-08 Country1 A 330

计算过程:

Plain 复制代码
Country1 = Province1 180 + Province2 150 = 330

完整上卷路径为:

Date → Month

City → Province → Country

3.5 一致性校验

层级 Revenue 总和
原始明细数据 330
Monthly City 330
Monthly Province 330
Monthly Country 330

因此满足:

plain 复制代码
明细层 Revenue
= 城市层 Revenue
= 省份层 Revenue
= 国家层 Revenue
= 330

最终的数据流可以概括为:
#mermaid-svg-ZRwDc5KEOkzcYCXC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZRwDc5KEOkzcYCXC .error-icon{fill:#552222;}#mermaid-svg-ZRwDc5KEOkzcYCXC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZRwDc5KEOkzcYCXC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .marker.cross{stroke:#333333;}#mermaid-svg-ZRwDc5KEOkzcYCXC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZRwDc5KEOkzcYCXC p{margin:0;}#mermaid-svg-ZRwDc5KEOkzcYCXC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster-label text{fill:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster-label span{color:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster-label span p{background-color:transparent;}#mermaid-svg-ZRwDc5KEOkzcYCXC .label text,#mermaid-svg-ZRwDc5KEOkzcYCXC span{fill:#333;color:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .node rect,#mermaid-svg-ZRwDc5KEOkzcYCXC .node circle,#mermaid-svg-ZRwDc5KEOkzcYCXC .node ellipse,#mermaid-svg-ZRwDc5KEOkzcYCXC .node polygon,#mermaid-svg-ZRwDc5KEOkzcYCXC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .rough-node .label text,#mermaid-svg-ZRwDc5KEOkzcYCXC .node .label text,#mermaid-svg-ZRwDc5KEOkzcYCXC .image-shape .label,#mermaid-svg-ZRwDc5KEOkzcYCXC .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZRwDc5KEOkzcYCXC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .rough-node .label,#mermaid-svg-ZRwDc5KEOkzcYCXC .node .label,#mermaid-svg-ZRwDc5KEOkzcYCXC .image-shape .label,#mermaid-svg-ZRwDc5KEOkzcYCXC .icon-shape .label{text-align:center;}#mermaid-svg-ZRwDc5KEOkzcYCXC .node.clickable{cursor:pointer;}#mermaid-svg-ZRwDc5KEOkzcYCXC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .arrowheadPath{fill:#333333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZRwDc5KEOkzcYCXC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZRwDc5KEOkzcYCXC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZRwDc5KEOkzcYCXC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster text{fill:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC .cluster span{color:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZRwDc5KEOkzcYCXC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZRwDc5KEOkzcYCXC rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZRwDc5KEOkzcYCXC .icon-shape,#mermaid-svg-ZRwDc5KEOkzcYCXC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZRwDc5KEOkzcYCXC .icon-shape p,#mermaid-svg-ZRwDc5KEOkzcYCXC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZRwDc5KEOkzcYCXC .icon-shape .label rect,#mermaid-svg-ZRwDc5KEOkzcYCXC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZRwDc5KEOkzcYCXC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZRwDc5KEOkzcYCXC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZRwDc5KEOkzcYCXC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 明细事实:Date + City + Product
月度城市汇总:Month + City + Product
月度省份汇总:Month + Province + Product
月度国家汇总:Month + Country + Product

这就是 ETL 中维度上卷的核心:维度层级向上提升,事实粒度变粗,同时按照目标粒度重新聚合度量值。

相关推荐
合众恒跃1 个月前
RK3588 + RK182X 双芯异构边缘计算方案:部署流程与实测性能解析
大数据·人工智能·科技·编辑器·etl工程师
陆水A1 个月前
【问数系统】SQL跑对了图表却空了?打通问数系统最后1公里的3个API坑
大数据·数据库·自然语言处理·big data·etl工程师
陆水A3 个月前
【实时数仓·2】CDC到Doris数据对不上——Sequence Column解了吗?
大数据·数据仓库·数据库开发·etl工程师·bigdata
JZC_xiaozhong3 个月前
企业微信集成OA、ERP与第三方应用:从“数据孤岛”到“流程闭环”
大数据·数据库·企业微信·etl工程师·持续集成·企业数据安全·数据集成与应用集成
陆水A3 个月前
用CASE WHEN实现横向迭代,节点数据串行推算
大数据·数据仓库·数据库开发·etl·etl工程师
陆水A4 个月前
运输时效预测模型:静态路由时效的计算与验证
大数据·人工智能·算法·spark·数据库开发·etl工程师
代码派5 个月前
信创迁移“不敢切”的最后一公里:数据一致性校验怎么做才算够?
数据库·数据库开发·dba·etl工程师·数据库管理工具·信创数据库·信创迁移
JZC_xiaozhong6 个月前
企业微信对接泛微OA:实现审批进度实时同步与自动催办
企业微信·etl工程师·泛微oa·数据集成与应用集成·业务流程管理系统·异构系统集成·跨系统流程管理
JZC_xiaozhong6 个月前
DCS分散控制系统与MES集成:实现制造过程数据贯通的关键路径
大数据·运维·制造·etl工程师·bpm·数据集成与应用集成·业务流程管理