2. 核心概念
好,咱们正式开始聊语义层的核心概念。说实话,我见过不少团队,一上来就急着写 SQL,结果业务方问一句「上个月的毛利率是多少」,就得改半天代码。为什么?因为底层没有把这些概念理清楚。
我个人习惯,在设计语义层之前,先把五个概念写在白板上:维度、度量、粒度、层次结构、计算成员。这五个词,就是语义层的「五官」。你想想看,五官不正,后面怎么化妆都别扭。
2.1 维度:你从哪个角度看数据?
维度,说白了就是「观察数据的角度」。比如「时间」、「地区」、「产品类别」——这些都是维度。它们回答的是「谁、什么、何时、何地」这类问题。
我在项目中遇到过最典型的坑:有人把「订单状态」和「支付状态」混在一个字段里。结果想统计「已支付未发货」的订单时,SQL 写得跟绕口令似的。嗯,这里要注意——每个维度应该只描述一个业务视角。
维度的核心特征:
- 离散性:取值是有限的、可枚举的(比如省份、月份)
- 描述性:提供上下文,不参与计算(「北京」不能加减)
- 层次性:可以向上或向下钻取(年→季度→月)
举个例子,一个「日期」维度,它的值可能是 2024-01-15。但你不会拿这个值去做加法,而是用它来筛选、分组、或者做趋势分析。
2.2 度量:你到底想算什么?
度量就是你要计算的数值。销售额、订单量、库存周转天数——这些都是度量。它们回答的是「多少」的问题。
度量有个关键属性:可加性。我习惯把度量分成三类:
| 类型 | 说明 | 例子 |
|---|---|---|
| 完全可加 | 跨所有维度都能直接求和 | 销售额、订单数量 |
| 半可加 | 只能沿部分维度求和 | 库存量(不能跨时间求和) |
| 不可加 | 不能直接求和 | 比率、单价、排名 |
我曾经帮一个零售客户排查报表,发现「库存周转天数」在汇总时直接求和了。结果集团看全国数据,显示周转天数 300 多天——这明显不对。后来改成加权平均,才恢复正常。
我的经验:定义度量时,一定要标注它的聚合方式。是 SUM、AVG、COUNT,还是更复杂的加权?写清楚,后面少踩一半的坑。
2.3 粒度:一行数据代表什么?
粒度,是语义层里最容易被忽略、但后果最严重的概念。它回答的是「每一行数据到底描述的是哪个级别的业务事件」。
举个例子:
- 「每笔订单一行」——粒度是订单
- 「每笔订单中的每个商品一行」——粒度是订单明细
- 「每个商品每天的库存快照一行」——粒度是商品+日期
你想想看,如果把订单明细和订单汇总混在一起做分析,那结果能对吗?我见过一个 BI 项目,就是因为粒度没对齐,导致「订单总数」和「商品销售件数」在同一个报表里差了 10 倍。排查了三天,最后发现是事实表关联时粒度膨胀了。
避坑指南:我曾经在金融项目中,把「交易流水」和「账户余额」放在同一个查询里。结果余额被重复加了好几遍。记住:不同粒度的事实表,不要直接 JOIN 后做聚合。要么先聚合再关联,要么用子查询隔离。
2.4 层次结构:钻取与上卷的骨架
层次结构,就是维度内部的组织关系。比如「年→季度→月→日」,或者「国家→省份→城市→门店」。
语义层里定义好层次结构,业务用户就能自由钻取。点一下「华北」,展开看到北京、天津、河北——这种体验,底层靠的就是层次结构。
我建议在建模时,把层次结构分成两类:
- 平衡层次:每一层的深度相同(比如日期维度,每层都有固定的下级)
- 参差不齐层次:某些分支的深度不同(比如组织架构,有的部门有 5 级,有的只有 3 级)
处理参差不齐层次时,我习惯用「桥接表」或者「路径枚举」的方式。嗯,这个后面讲高级建模时会细说。
2.5 计算成员:不存数据,却能算数据
计算成员,就是那些不在原始表中、但通过已有度量计算出来的「虚拟度量」。比如「利润率 = 利润 / 销售额」、「同比增长率 = (本期 - 同期) / 同期」。
它的好处很明显:
- 数据不用重复存储
- 计算逻辑统一,不会出现「A 部门用除法,B 部门用减法」的混乱
- 修改公式时,只改一处,全局生效
我在项目中遇到过最典型的场景:财务部门要求「毛利率」保留两位小数,但销售部门要四位。如果各自写 SQL,迟早会出不一致。后来在语义层里统一用一个计算成员,两边引用同一个定义,问题就解决了。
计算成员的典型写法(以 MDX 为例):
MEMBER [Measures].[毛利率] AS
[Measures].[毛利] / [Measures].[销售额],
FORMAT_STRING = '0.00%'
在 SQL 语义层中,通常用 WITH 子句或视图来实现类似效果。
2.6 五个概念的关系图
下面这张图,是我每次培训时必画的。它把五个概念串在了一起:
你看,事实表在中间,四周是维度,头顶是粒度,脚下是计算成员,两侧是层次结构。这五个概念一旦对齐,整个语义层就稳了。
2.7 小结:先画图,再写代码
我个人习惯,每接手一个新项目,第一件事不是打开 SQL 客户端,而是拿白板把这五个概念画一遍。维度有哪些?度量怎么聚合?粒度是什么?层次结构怎么走?计算成员需要几个?
这些问题想清楚了,后面的建模、ETL、报表开发,都是水到渠成的事。你想想看,如果连「一行数据代表什么」都没搞明白,写出来的查询能靠谱吗?
一个小技巧:下次开会讨论报表需求时,试着用这五个概念去拆解业务方的描述。你会发现,很多模糊的需求一下子就清晰了。比如对方说「我要看每个月的销售情况」,你可以追问:「这个『销售情况』是指订单金额还是利润?粒度是按订单还是按商品?」——几句话就能把需求定死,避免后期返工。