Lazy loaded imagePowerBI、PowerQuery中什么是事实表和维度表?

type
status
date
slug
summary
tags
category
icon
password

三个核心概念的简述

首先,想象一下事实表(Fact Table)。

它就是整个故事的“动作记录本”或“事件日志”。它只关心发生了什么具体、可量化的动作。比如,一个顾客买了一件商品,这就是一个动作。事实表会用最精简的方式记录下来:在什么时间点(一个代码),谁(一个代码),买了什么(一个代码),在哪个地方(一个代码),买了多少个,花了多少钱。所以,这张表充满了数字和代码,它非常的长,因为业务中的动作每时每刻都在发生,它就像一条无限延伸的流水账,只记录动作本身,而不解释这些代码的含义。
这是记录所有交易动作的核心。它非常长,充满了数字和ID。
表名:Fact_Sales
解读:
  • SalesTransactionID (PK) 是这张表自己的主键,确保每一条交易记录都是唯一的。
  • 其他所有的“键”都是外键(FK),它们是连接到外部“字典”(维度表)的桥梁。
  • SalesQuantity 和 SalesAmount 是度量,是我们最终要进行计算的数值。
  • 注意看,ProductKey = 101 和 StoreKey = 1 这两个ID在表中反复出现,因为这个商品在这个门店被多次购买。
SalesTransactionID (PK)
DateKey (FK)
ProductKey (FK)
StoreKey (FK)
CustomerKey (FK)
SalesQuantity
SalesAmount
1001
20230115
101
1
58
2
12.00
1002
20230115
210
1
58
1
15.00
1003
20230208
105
2
112
3
16.50
1004
20230220
102
2
23
1
6.50
1005
20230310
102
1
112
10
65.00
1006
20230312
301
3
58
1
99.00
...
...
...
...
...
...
...

接着,是维度表(Dimension Table)。

如果事实表是动作记录,那么维度表就是这个故事的“背景设定集”或“演员名录”。事实表里的那些代码,比如“顾客代码58号”,本身毫无意义。维度表的作用就是来解释这些代码的。它会告诉你:顾客代码58号,指的是张伟先生,他住在上海,是个金牌会员。产品代码101号,指的是光明牌经典纯牛奶。所以,维度表提供的是上下文,它描述的是参与到动作中的那些人、事、物、地点和时间的详细属性。它就像一本本厚厚的字典,专门用来查询事实表里的代码到底代表什么。维度表下面还有更细的维度表,称之为卫星表(Satellite Table),比如分类表。有时候,一本“字典”里的信息太复杂了,它自身也需要一个“索引”或“附录”。这就是卫星表的作用。想象一下我们的“产品”这本大字典(产品维度表),里面有成千上万个商品。我们会发现,很多商品的分类都是“乳制品”,品牌都是“光明”。如果每一行都重复写一遍“乳制品-牛奶”或者“光明”,会非常冗余和浪费。
于是,我们把“分类”这个属性单独抽出来,做成一本更小的、专门的“分类字典”(这就是卫星表)。这本小字典里定义好了:代码50代表“乳制品-牛奶”。然后,在“产品”这本大字典里,我们不再写冗长的文字,只需要记录这个产品的分类代码是50就行了。这样,主字典变得更整洁,而分类信息由专门的卫星字典来维护,整个结构就像行星(主维度表)带着自己的卫星(分类表)一样。
这是提供上下文的“字典”和“字典的附录”。

1. 主维度表 (Dimension Tables)

表名:Dim_Date
DateKey (PK)
FullDate
Year
Quarter
Month
DayOfWeek
20230115
2023-01-15
2023
Q1
1月
星期日
20230208
2023-02-08
2023
Q1
2月
星期三
20230220
2023-02-20
2023
Q1
2月
星期一
20230310
2023-03-10
2023
Q1
3月
星期五
20230312
2023-03-12
2023
Q1
3月
星期日
...
...
...
...
...
...
表名:Dim_Store
StoreKey (PK)
StoreName
City
Province
1
人民广场店
上海
上海市
2
国贸店
北京
北京市
3
徐家汇店
上海
上海市
...
...
...
...
表名:Dim_Product (被雪花化改造后的主维度表)
解读: 这张表现在很“瘦”。它不再包含品牌和分类的文字,而是用 BrandKey 和 CategoryKey 这两个外键,指向了更小的卫星表。
ProductKey (PK)
ProductName
BrandKey (FK)
CategoryKey (FK)
101
经典纯牛奶250ml
8
50
102
高钙纯牛奶250ml
8
50
105
原味酸奶100g
9
51
210
切片面包450g
12
65
301
精品拿铁咖啡
15
70
...
...
...
...

2. 卫星表 (Satellite Tables)

表名:Dim_Brand
解读: 这是一个专门的品牌“小字典”。“光明”只在这里出现一次。
BrandKey (PK)
BrandName
8
光明
9
伊利
12
桃李
15
星巴克
...
...
表名:Dim_Category
解读: 这是一个专门的分类“小字典”。“乳制品-牛奶”这个组合也只出现一次。
CategoryKey (PK)
CategoryName
SubCategoryName
50
乳制品
牛奶
51
乳制品
酸奶
65
粮油副食
面包
70
饮品
咖啡
...
...
...

超市销售场景下的三者关系串联


 
现在,让我们以一个完整的超市销售分析问题,来把这三者的关系生动地串联起来。
分析任务: 业务总监想知道,“上个季度,‘光明’品牌旗下的‘牛奶’类商品,在上海所有门店的总销售额是多少?
作为数据分析师,你的大脑(或者说Power BI)会像下面这样,在这三类表之间穿梭,来寻找答案:

第一站:从动作日志出发——事实表

你的旅程始于数据海洋的中心——那张拥有数百万行记录的事实表。你首先根据“上个季度”这个时间要求,筛选出所有发生在这个时间段内的销售记录。此时,你得到了一张巨大的、临时的流水账清单,但上面全是代码,比如:
  • 日期键=20230315, 产品键=101, 门店键=1, 销售金额=6.00
  • 日期键=20230316, 产品键=210, 门店键=2, 销售金额=15.00
  • ...成千上万条类似记录

第二站:寻找上下文——维度表与它的卫星们

这些代码无法直接回答问题,你需要去“字典”里查找它们的含义。
  1. 解码“上海门店”:你拿着事实表里所有的门店键,去查阅门店维度表。在这本字典里,你找到了所有“所在城市”属性为“上海”的门店,并记下它们的门店键(比如,1号、3号、8号门店都在上海)。
  1. 解码“光明的牛奶” - 这里体现了卫星表的威力
      • 你不能直接去产品维度表里找,因为那里可能没有直接的品牌和分类文字。所以,你先去了更小的“附录字典”——品牌卫星表。在这里,你查到“光明”这个品牌的代码是 品牌键=8。
      • 接着,你又去了另一本“附录字典”——分类卫星表。在这里,你查到“牛奶”这个子分类的代码是 分类键=50。
      • 现在,你手握两个关键代码(品牌键=8 和 分类键=50),回到了主要的产品维度表。你在这本大字典里,筛选出所有同时满足“品牌代码是8”并且“分类代码是50”的商品,并记下它们所有的产品键(比如,101号、102号、103号...都是光明的牛奶)。

最后一站:回到中心,完成计算——事实表

现在,你已经集齐了所有“密码”:
  • 一个上个季度的时间范围。
  • 一个代表上海所有门店的门店键列表。
  • 一个代表所有光明牛奶的产品键列表。
你带着这些密码,再次回到那张巨大的事实表。你对它下达最终指令:请找出所有同时满足这三个密码条件的记录,然后,把这些记录的销售金额这一列的数字,全部加起来!
最终,电脑吐出了一个数字:5,230,000元。
这个数字,就是通过事实表记录的动作、维度表提供的背景、以及卫星表提供的精细化索引,三者紧密协作,共同演绎出的商业洞察。

三者关系的完整串联 — 解答分析任务

分析任务: “上个季度(假设为2023年Q1),‘光明’品牌旗下的‘牛奶’类商品,在上海所有门店的总销售额是多少?
  1. 锁定品牌和分类 (查询卫星表)
      • 在 Dim_Brand 表中,找到 BrandName = '光明',得到 BrandKey = 8。
      • 在 Dim_Category 表中,找到 SubCategoryName = '牛奶',得到 CategoryKey = 50。
  1. 锁定产品 (查询主维度表)
      • 拿着 BrandKey = 8 和 CategoryKey = 50 这两个ID,去查询 Dim_Product 表。
      • 找到所有同时满足这两个ID的行,得到一个产品ID列表:ProductKey IN (101, 102)。
  1. 锁定门店 (查询主维度表)
      • 在 Dim_Store 表中,找到所有 City = '上海' 的行,得到一个门店ID列表:StoreKey IN (1, 3)。
  1. 锁定时间 (查询主维度表)
      • 在 Dim_Date 表中,找到所有 Quarter = 'Q1' 且 Year = 2023 的行,得到一个日期ID列表:DateKey IN (20230115, 20230208, ...)。
  1. 最终查询事实表 (在“动作记录本”中汇总)
      • 现在,我们带着所有筛选条件,回到 Fact_Sales 表。
      • 指令是:请找出所有满足以下所有条件的行:
        • DateKey 在Q1的日期列表中
        • ProductKey 在 (101, 102) 列表中
        • StoreKey 在 (1, 3) 列表中
      • 根据我们上面示例的数据,符合条件的记录有:
        • SalesTransactionID = 1001: (DateKey=20230115, ProductKey=101, StoreKey=1) -> SalesAmount = 12.00
        • SalesTransactionID = 1005: (DateKey=20230310, ProductKey=102, StoreKey=1) -> SalesAmount = 65.00
      • 将这些记录的 SalesAmount 相加:12.00 + 65.00 = 77.00。
最终答案: 根据这份样本数据,上季度光明牛奶在上海的总销售额是 77.00 元。这个答案是通过在不同类型的表之间层层导航、筛选、最终在事实表完成聚合计算而得到的。

【点击文末“阅读原文”,获取本文及历史以来提及、发布的相关精选和原创资料,和我们一起充电,加入后可享受每月6次免费咨询提问,帮助解决您的特定问题!】

如果本篇文章对您有帮助或启发,请帮我们点赞、转发、推荐、关注,让更多想转型财务BP、锻造数据分析和可视化洞察能力的财务同行们看到,关注【老汪洞察】,不迷路!
 
温馨提示
🙏🏻
如果您不想错过【老汪洞察】的文章,请将我们设为"星标",这样每次最新文章推送才会第一时间出现在您的订阅列表里。 方法:点击文章页面左上角蓝色文字“老汪洞察”进入主页,点击关注后,再点主页右上角"...",然后选择"设为星标",即可完成,感谢您的支持。
         长按二维码识别后进入
长按二维码识别后进入
上一篇
PowerQuery功能详解之添加自定义列
下一篇
数据分析与可视化的基础材料:从二维表与多维表的细分谈起
Loading...
文章列表
让财税成为经营的力量
电脑与网络
从Power Query到Power BI,入门到精通
知识运用