什么是 Auto-Exists
Auto-Exists 使查询结果只显示现有属性的组合。以超市销售数据为例,在电器类目下显示空调的销售数量是有意义的,显示衬衫是无意义的,因为电器类目下没有衬衫这个 SKU。虽然类目和产品来自不同的列,但是 Auto-Exists 确保两者不会出现错配,只包含现有的属性组合。
触发条件
Auto-Exists 是 SSAS 的一项功能,在所有运行 DAX 或者 MDX 的客户端都能观察到它的存在。当同一个表的两个或多个列被同时筛选时,Auto-Exists 机制就会发挥作用。
理解 Auto-Exists
让我们以下图中的数据模型为例来理解 Auto-Exists。
在这个模型中,产品类别列和子类别列的排列既采用了规范化也采用了反规范化
在模型中,产品、子类别和类别之间存在筛选关系。利用 RELATED 函数,我们还在产品表中添加了反规范化的产品类别和子类别。
Product 表原本不存在红框中的两列,通过 RELATED 我们将产品类别和产品子类别进行了反规范化,现在它们都在产品表中新建了副本。
基于此模型,你可以轻松构建两个数据透视表,显示按类别和子类别划分的销售额。乍一看,他们的结果是相同的
两种模型的展示结果相同
实际上,DAX 以两种不同的方式计算两个透视表,其实是由于两个不同特性作用于标准查询才提供了相同的结果。它们是自动匹配(Auto-Exists)和移除空行(Empty Row Removal)。Auto-Exists 是服务器特性,而移除空行是透视表特性。让我们来更详细地分析一下它们。
- 反规范化模型使用 Auto-Exists 避免对不存在的集合进行计算。事实上,虽然计算(Audio, MP4&MP3)组合的销售额是有意义的,但是为(Audio, Camcorders)组合进行相同的计算是没有意义的,因为摄像机这个子类别根本不属于音频类别。因此,由于没有同时属于摄像机和音频的产品,DAX 完全可以避免计算这个值,从而减少报表的整体计算时间。
- 规范化模型使用移除空行达到与 Auto-Exists 相同的效果,这是透视表默认启用的特性,如果当前行所有度量值都为空,它会自动隐藏该行。例如,如果有一个产品从来没有被卖出过,那么透视表就会隐藏它,因为这一行不会包含任何有用的信息。
认识移除空行
移除空行位置示意
需要再次强调的是,Auto-Exists 是服务器特性,而移除空行是透视表特性。你可以通过在透视表选项中选择“显示行中的空数据项”复选框来控制移除空行的行为;通过这种方式,你可以禁用移除空行,此时两个表的结果将产生显著区别,如下图所示。
禁用透视表的移除空行,将使两表显示不同的结果
自动匹配与移除空行的内在区别
如果禁用移除空行,规范化模型会对不存在的类别与子类别组合执行计算。另一方面,在反规范化模型中,只对现有组合进行计算。反规范化模型以不同方式运行的原因是由于 Auto-Exists。右侧透视表的两列属于同一个表,所以引擎第一步先确定现有的组合,然后才计算有效值。在 DAX 中,通过以下两个查询模拟,你会注意到这种差异:
- ------------- 规范化模型 -------------
- EVALUATE
- ADDCOLUMNS (
- CROSSJOIN (
- VALUES ( 'Product Category'[Category] ),
- VALUES ( 'Product Subcategory'[Subcategory] )
- ),
- "Sales Amount", [Sales Amount]
- )
- ------------ 反规范化模型 -------------
- EVALUATE
- SUMMARIZECOLUMNS (
- 'Product Category'[Category],
- 'Product Subcategory'[Subcategory],
- "Sales Amount", [Sales Amount]
- )
复制代码
第一个查询使用 CROSSJOIN,返回不存在的类别和子类别组合,第二个查询使用 SUMMARIZE 只返回存在的组合。
Power BI 中的 Auto-Exists
虽然 Power BI 不提供 Excel 移除空行的特性,但会在查询中隐式加入判断当前维度组合行数的度量值,来实现同样的效果,所以即使作为维度的列来自不同的表,Power BI 也默认只显示存在的组合:
矩阵只保留了源数据中存在的组合
用来生成的矩阵的查询
Auto-Exists 的潜在影响
到目前为止,这种差异看起来很微妙,似乎无伤大雅。实际上,当你开始编写修改筛选上下文的度量值,在 CALCULATE 中加入筛选器参数时,Auto-Exists 就变得非常重要。如果你不理解这种行为,很可能会认为公式出了 Bug。例如,假设你编写了一个度量值来计算音频类别的销售额,如下所示:
- [Audio Sales] :=
- CALCULATE (
- [Sales Amount],
- 'Product Category'[Category] = "Audio"
- )
复制代码
显然,两种模型下的公式运行略有不同,但逻辑是一致的。但你会发现使用这个度量值透视表产生了令人惊讶的结果,如图所示:
Audio Sales 在规范化模型(左表)中显示了奇怪的结果
你可以在反规范化模型中看到音频产品的销售仅在音频类别下可见。在左侧的规范化模型中,透视表显示了相机和摄像机类别下的音频产品销售情况。这一次,即使启用了移除空行,这两个透视表的结果也是不同的。
原因并不难理解。度量值 Audio Sales 将类别上的筛选器替换为固定值“Audio”。“在反规范化模型中,这对 Cameras and Camcorders 类别没有影响,因为 SUMMARIZECOLUMNS 的作用,引擎将类别和子类别的组合作为筛选器,只计算相机和摄像机类别下的子类别的值。然而,在规范化模型中由于其内部使用 CROSSJOIN,引擎将类别和子类别作为独立的筛选器,对类别和子类别的所有组合(无论它们是否存在)计算度量值。当 DAX 计算<Cameras and Camcorders, Bluetooth Headphones>组合的值时,它遵循 CALCULATE 计值流,用 Audio 替代当前类别,从而得到<Audio、Bluetooth Headphones>的组合,后者可以被有效计算并显示在透视表中。
结合数据模型一文中的星型模型的价值:
- 不同类型的维度分别建表,彼此之间的组合使用 CROSSJOIN,这符合我们惯常的逻辑
- 同一类型的维度汇总到一张表,比如产品名称-产品子类别-产品类别的组合。使其内部可以使用 Auto-Exists 执行计算,避免了无意义的组合
基于这两点,我们推荐星型架构作为 Power BI 的主模型架构
当然,某些特殊情况下(比如上文潜在影响中的案例)你希望避免 Auto-Exists 时,使用规范化的模型是一个好方法。比如将产品名称-产品子类别-产品类别拆分为三张表。请记住 Auto-Exists 只对来自同一表的列集有效,这就是为什么上面的案例中反规范化模型能正常工作,而规范化模型却不能。
Power BI 数据建模的黄金规则是始终使用星型模型,星型模型从事实表中扫描值,而 Auto-Exists 只在维表上生效,这不会产生任何问题。如果必须使用列来切片或筛选,那么它需要存放于维表中。而用于聚合的数值最好存储在事实表中。
7139211936398.rar
(1.83 MB, 下载次数: 0)
|