一对一关系指南

本文专为使用 Power BI Desktop 的数据建模人员设计。 它指导你如何处理一对一模型关系。 如果两个表都包含一列唯一公用值,可以创建一对一关系。

注意

本文不涵盖对模型关系的介绍。 如果你对模型关系、其属性或配置方法并非完全熟悉,建议先阅读 Power BI Desktop 中的模型关系一文。

此外,还应了解星型架构设计,这一点也很重要。 有关详细信息,请参阅了解星型架构和 Power BI 的重要性

涉及一对一关系的场景有以下两种:

  • 退化维度:可从事实数据表派生一个退化维度

  • 行数据跨表:单个业务实体或主题加载为两个(或更多)模型表,可能是因为它们的数据源来自不同的数据存储。 此方案对于 维度表很常见。 例如,主产品详细信息存储在运营销售系统中,而附属产品详细信息则存储在其他源中。

    但是,将两个事实表与一对一关系相关联是不寻常的。 这是因为这两个事实数据表都需要具有相同的维度和粒度。 此外,每个事实数据表都需要唯一的列才能创建模型关系。

退化维度

当事实数据表中的列用于筛选或分组时,可以考虑在单独的表中提供它们。 这样一来,就可以将用于筛选或分组的列与用于汇总事实行的列分隔开来。 这种分隔可以:

  • 减少存储空间。
  • 简化模型计算。
  • 有助于提高查询性能。
  • 向报表作者提供更直观的“数据”窗格体验。

请考虑名为 Sales 的源表,该表将销售订单行引用详细信息存储在两列中。

关系图显示了 Sales 退化维度表的表行。设计在下一段落中进行介绍。

OrderNumber 列存储订单号,OrderLineNumber 列存储订单中的一系列订单项。

在下图中,请注意,订单号和订单行号列尚未加载到 Sales 表中。 而它们的值用于创建名为 OrderLineNumberID代理键列。 (键值的计算方法为,将订单号乘以 1000,然后再加上订单项号。)

关系图显示了两个表:Sales 和 Sales Order。一对一关系将两个“订单行号 ID”列关联起来。

Sales Order 维度表为报表作者提供了丰富的体验,其中包含两列:Sales OrderSales Order Line。 这些特定列资源支持需要对订单和订单行进行筛选、分组或向下钻取的报表设计。

由于 Sales Order 表派生自销售数据,因此每个表中的行数应完全相同。 此外,每个 OrderLineNumberID 列之间应有匹配的值。

跨表的行数据

请考虑涉及两个一对一相关维度表的示例:ProductProduct Category。 每个表表示导入的数据,并具有一个包含唯一值的 SKU(保留单位)列。

下面展示了这两个表的部分模型图。

图示显示一个包含两个表格的模型,其中的行数据跨越这两个表格。以下段落介绍了设计。

第一个表命名为 Product,其中包含三列:ColorProductSKU。 第二个表命名为 Product Category,其中包含两列:CategorySKU。 一对一关系将两个 SKU 列关联起来。 关系为双向筛选,对于一对一关系,总是如此。

为了帮助描述关系筛选器传播的工作原理,下图显示了一些表行。 本文中的所有示例都以此数据为依据。

关系图显示了 Product 和 Product Category 表及一些数据行。行详细信息在下一段落中进行介绍。

下面的项目符号列表描述了两个表的行的详细信息:

  • 编号为 Product 的表共有三行:
    • SKU CL-01、 ProductT 恤、Color绿色
    • SKUCL-02Product牛仔裤Color蓝色
    • SKU AC-01、Product帽子、Color蓝色
  • Product Category 表有两行:
    • SKU CL-01、Category服装
    • SKUAC-01Category配件

请注意,Product Category 表中不包含产品 SKU CL-02的一行。 本文稍后将讨论缺少此行的结果。

在“数据”窗格中,报表作者在两个表中查找与产品相关的字段:ProductProduct Category。 现在来看看添加有两个表中字段的表视觉对象是什么样的。 在此示例中,SKU 列源自 Product 表。

关系图显示了包含两个表的数据窗格,以及一个包含四列的表视觉对象。产品 SKU CL-02 的“类别”值为 BLANK。

请注意,产品 SKU CL-02Category 值为 BLANK。 这是因为此产品的 Product Category 表中没有相应的行。

建议

若为跨模型表的行数据,建议尽可能避免创建一对一模型关系。 这是因为此设计可以:

  • 导致“数据”窗格混乱,列出不必要的表。
  • 导致报表作者很难找到相关字段,因为它们分布在多个表中。
  • 限制创建层次结构的能力,因为其级别必须基于同一表中的列。
  • 在表之间的行不完全匹配时导致意外结果出现。

具体建议因一对一关系是源组内还是跨源组而异 。 有关关系评估的详细信息,请参阅 Power BI Desktop中的 模型关系。

源组内一对一关系

如果表之间是一对一源组内关系,建议将数据合并到一个模型表中。 可以通过合并 Power Query 查询来执行此操作。

以下步骤提供了一种合并和建模一对一相关数据的方法。

  1. 合并查询合并两个查询时,考虑每个查询中数据的完整性。 如果一个查询包含一组完整的行(如主列表),请将另一个查询与它合并。 将合并转换设置为使用左外部联接(即默认联接类型)。 这种联接类型可确保你保留第一个查询的所有行,并使用第二个查询的任何匹配行进行补充。 将第二个查询的所有必需列扩展到第一个查询中。

    关系图显示了合并到单个产品维度表中的数据。

  2. 禁用查询负载:请务必对第二个查询禁用负载。 这样,它就不会将其结果加载为模型表。 此配置减少了数据模型存储大小,并有助于让“数据”窗格保持整洁。

    在我们的示例中,报表作者现在可在“数据”窗格中找到一个名为 Product 的表。 它包含所有与产品相关的字段。

  3. 替换缺失值:如果第二个查询包含不匹配的行,那么从它引入的列中会显示 null 值。 视情况考虑使用标记值替换 null 值。 当报表作者按列值筛选或分组时,替换缺少的值尤为重要,因为报表视觉对象中可能会显示 BLANK。

    在下图中,请注意,产品 SKU CL-02 的类别现在显示为 [未定义]。 在查询中,null 类别已替换为此标记文本值。

    关系图显示了 Product 表的“数据”窗格。它还显示一个包含四列的表视觉对象。产品 SKU CL-02 的“类别”值现在标记为“未定义”。

  4. 创建层次结构:如果当前合并的表的列之间 存在关系,不妨创建层次结构。 这样,报表作者会快速发现报表视觉对象钻取机会。

    在我们的示例中,报表作者现在可以使用具有两个级别的层次结构:CategoryProduct

    关系图显示了“数据”窗格。Product 表包含“产品”层次结构。

如果你更倾向于单独的表有助于整理字段,仍建议合并到单个表中。 仍可以整理字段,但要改用显示文件夹 。

在我们的示例中,报表作者可以在 Marketing 显示文件夹中找到 Category 字段。

图表显示

如果你仍决定在模型中定义一对一源组内关系,请尽可能确保关联表中有匹配行。 由于一对一源组内关系被评估为常规关系,因此数据完整性问题可能会在报表视觉对象中显示为空白。 (例如,本文中显示的第一个表视觉对象中就有 BLANK 分组。)

跨源组一对一关系

如果表之间是一对一跨源组关系,除非预先合并数据源中的数据,否则没有替换模型设计。 Power BI 会将一对一模型关系评估为有限关系。 因此,请注意确保相关表中有匹配的行,因为查询结果中会剔除不匹配的行。

关系图显示了跨源组一对一关系,这是一种有限关系。

现在来看看添加有这两个表(之间存在有限关系)中的字段的表视觉对象是什么样的。

关系图显示了两个表视觉对象,这些视觉对象在下一段落进行介绍。

使用跨源组关系的第一个表视觉对象仅显示两行。 缺少产品 SKU CL-02,因为 Product Category 表中没有匹配行。 第二个表视觉对象基于模型中的单个合并表,显示三行。

有关本文的详细信息,请参阅以下资源: