关系

适用于: SQL Server Analysis Services Azure Analysis Services Fabric/Power BI Premium

在表格模型中,关系是两个数据表之间的连接。 该关系确立两个表中的数据应该如何相关。 例如,Customers 表和 Orders 表可以彼此相关,以便显示与每个订单关联的客户名称。

从同一数据源导入时,将在模型中重新创建 (数据源) 的表中已存在的关系。 通过使用关系图视图中的模型设计器或使用“管理关系”对话框,可以查看检测到的关系和自动重新创建的关系。 还可以通过使用关系图视图中的模型设计器或使用“创建关系”或“管理关系”对话框,手动创建表之间的新关系。

在定义了两个表之间的关系(在导入过程中自动创建或手动创建)之后,便能够使用相关列筛选数据以及在相关表中查找值。

提示

如果您的模型包含多个关系,则关系图视图可以更好地展现表之间的关系和创建新关系。

好处

关系是两个数据表之间的连接,它基于每个表中的一列或多列。 要理解关系为何有用,可以想像一下在业务中跟踪客户订单数据。 可以在具有以下结构的一个表中跟踪所有数据:

CustomerID 名称 EMail DiscountRate OrderID OrderDate 产品 数量
1 Ashton chris.ashton@contoso.com .05 256 2010-01-07 Compact Digital 11
1 Ashton chris.ashton@contoso.com .05 255 2010-01-03 SLR Camera 15
2 Jaworski michal.jaworski@contoso.com .10 254 2010-01-03 Budget Movie-Maker 27

这种方法可以用,但会存储大量冗余数据,如每个订单的客户电子邮件地址。 存储成本低廉,但如果电子邮件地址发生更改,就必须确保更新该客户的每一行数据。 针对这一问题,一种解决方法是将数据拆分到多个表中,然后在这些表之间定义关系。 这是关系数据库(如 SQL Server)中使用的方法。 例如,导入模型的某个数据库可以使用三个相关表来表示订单数据:

客户

[CustomerID] 名称 电子邮件
1 Ashton chris.ashton@contoso.com
2 Jaworski michal.jaworski@contoso.com

CustomerDiscounts

[CustomerID] DiscountRate
1 .05
2 .10

Orders

[CustomerID] OrderID OrderDate 产品 数量
1 256 2010-01-07 Compact Digital 11
1 255 2010-01-03 SLR Camera 15
2 254 2010-01-03 Budget Movie-Maker 27

如果从同一数据库导入这些表,Import 可以根据 [brackets] 中的列检测表之间的关系,并且可以在模型设计器中重现这些关系。 有关详细信息,请参阅本文中的关系自动检测和推理部分。 如果从多个源导入表,则可以按照创建 两个表之间的关系中所述手动创建关系

列和键

关系基于每个表中包含相同数据的列。 例如,Customers 和 Orders 表可以彼此相关,因为它们都包含存储客户 ID 的列。 在本示例中,列名称相同,但这不是必需的。 只要 Orders 表的所有行都包含也存储在 Customers 表中的 ID,一列可以是 CustomerID,另一列可以是 CustomerNumber。

在关系数据库中,有几种类型的键 ,键通常是具有指定属性的列。 在关系数据库中,可以使用以下四种类型的键:

  • 主键:唯一标识表中的一行,如 Customers 表中的 CustomerID。

  • 备用键 (或 候选键):主键之外的唯一列。 例如,Employees 表可能存储雇员 ID 和社会保障号,这两者都是唯一的。

  • 外键:引用另一表中唯一列的列,如 Orders 表中的 CustomerID(可引用 Customers 表中的 CustomerID)。

  • 组合键:由多列组成的键。 表格模型中不支持组合键。 有关详细信息,请参阅本文中的复合键和查阅列部分。

在表格模型中,主键或备用键称为“相关查找列” 或“查找列” 。 如果表既有主键又有备用键,则主键和备用键都可作为查找列。 外键称为“源列” 或简单地称为“列” 。 在我们的示例中,将在 Orders 表的 CustomerID(列)和 Customers 表的 CustomerID(查找列)之间定义关系。 如果从关系数据库导入数据,默认情况下,模型设计器会从一个表中选择外键,从另一个表中选择相应的主键。 但是,您可以将具有唯一值的任意列用作查找列。

关系类型

Customers 与 Orders 之间的关系是“一对多关系”。 每个客户都可以有多个订单,但一个订单不能有多个客户。 其他关系类型还有“一对一”和“多对多”。 为每个客户定义一个折扣率的 CustomerDiscounts 表与 Customers 表具有一对一关系。 Products 和 Customers 之间的直接关系就是多对多关系的一个示例,在这种关系中,一个客户可以购买多种产品,同一种产品可由很多客户购买。 在用户界面中,模型设计器不支持多对多关系。 有关详细信息,请参阅本文中的多对多关系部分。

下表显示了三个表之间的关系:

关系 类型 查找列
Customers-CustomerDiscounts 一对一 Customers.CustomerID CustomerDiscounts.CustomerID
Customers-Orders 一对多 Customers.CustomerID Orders.CustomerID

关系和性能

在创建任何关系之后,对于任何公式,如果它们使用新创建的关系中所涉及的各表中的列,模型设计器通常必须对其进行重新计算。 处理可能需要一些时间,这取决于数据量和关系的复杂度。

Requirements for relationships

创建关系时,模型设计器必须遵守几项要求:

表之间的单个活动关系

多个关系会导致表之间存在不明确的依赖关系。 若要创建准确的计算,需要从一个表到下一个表的单一路径。 因此,每对表之间只能存在一个活动关系。 例如,在 AdventureWorks DW 2012 中,表 DimDate 包含一个列 DateKey,该列与表 FactInternetSales 中的以下三个不同列相关:OrderDate、DueDate 和 ShipDate。 如果您试图导入这些表,则会成功创建第一个关系,但是在创建涉及相同列的后续关系时会接收到下面的错误:

* 关系:table[column 1]-> table[column 2] - Status: error - 原因:无法在表 1> 和<表 <2> 之间创建关系。 在两个表之间只能存在一个直接或间接关系。

如果您有两个表并且这两个表之间存在多个关系,则需要导入包含查找列的表的多个副本,并在每对表之间创建一个关系。

表之间可以有许多非活动关系。 表之间要使用的路径在查询时由报表客户端指定。

每个源列具有一个关系

源列无法具有多个关系。 如果您已在一个关系中将某列用作源列,但希望使用该列连接到其他表中的另一个相关的查找列,则可以创建该列的副本并使用该列创建新的关系。

可使用计算列中的 DAX 公式轻松创建具有完全相同值的列的副本。 有关详细信息,请参阅 创建计算列

每个表的唯一标识符

每个表都必须具有一个单独的列,用于唯一标识该表中的每一行。 该列通常称为主键。

唯一查找列

查找列中的数据值必须是唯一的。 也就是说,该列不能包含重复值。 在表格模型中,Null 和空字符串等效于空白,而空白是一种独特的数据值。 这意味着查找列中不能包含多个 Null 值。

兼容的数据类型

源列和查找列中的数据类型必须兼容。 有关数据类型的详细信息,请参阅 支持的数据类型

组合键和查找列

不能在表格模型中使用组合键;必须始终有一列来唯一标识表中的每一行。 如果尝试导入具有基于复合键的现有关系的表,导入将忽略该关系,因为无法在表格模型中创建它。

如果要在模型设计器中创建两个表之间的关系,并且存在多个定义主键和外键的列,必须先组合这些值创建一个键列,然后才能创建关系。 您可以在导入数据之前执行此操作,也可以在模型设计器中通过创建计算列来执行此操作。

多对多关系

1500 及更高兼容性级别的表格模型部署到 Azure Analysis Services、SQL Server 2019 及更高版本的 Analysis Services,Power BI Premium支持多对多关系。

多对多关系是表之间的关系,其中两列都是非唯一的。 可以在维度和事实表之间以高于维度的键列的粒度定义关系。 这样避免了对维度表进行标准化并且可以改善用户体验,因为生成的模型具有较少带有逻辑分组列的表。

使用 Visual Studio 2019 和 Analysis Services 项目、表格对象模型 (TOM) API、表格模型脚本语言 (TMSL) 和开源表格编辑器工具来创建多对多关系。

兼容级别为 1400 和更低级别的表格模型不支持多对多关系,并且无法在模型设计器中添加 交汇点表 。 但可以使用 DAX 函数为多对多关系建模。 你还可以尝试设置双向交叉筛选器以查看它是否实现同一目的。 有时,可以通过跨多个表关系保留筛选器上下文的交叉筛选器来满足多对多关系的要求。 有关详细信息,请参阅 表格模型中的双向交叉筛选器

自联接和循环

表格模型表中不允许使用自联接。 自联接是一个表与其自身之间的递归关系。 自联接通常用于定义父子层次结构。 例如,可以将 Employees 表联接到其自身,从而生成显示业务管理链的层次结构。

模型设计器不允许在模型中的关系之间创建循环。 换言之,禁止使用下面这组关系。

表 1,列 a 到表 2,第 f 列

表 2,第 f 列到表 3,第 n 列

表 3,第 n 列到表 1,列 a

如果您试图创建的关系会导致创建循环,则会生成错误。

Inference of relationships

在某些情况下,表之间的关系会自动链接。 例如,如果在以下前两组表之间创建关系,则会推断出其他两个表之间存在一个关系,进而自动建立一个关系。

Products 和 Category -- 手动创建

Category 和 SubCategory -- 手动创建

Products 和 SubCategory -- 推断出关系

为使关系自动链接,关系方向必须相同,如上所示。 例如,如果初始关系是在 Sales 和 Products 以及 Sales 和 Customers 之间,则不会推断出关系。 这是因为 Products 和 Customers 之间的关系是多对多关系。

Detection of relationships when importing data

从关系数据源表导入时,将根据源架构数据检测表之间的现有关系。 如果导入相关表,则会在模型中复制这些关系。

Manually create relationships

尽管单个关系数据源中的表之间的大多数关系将会被自动检测到并且在表格模型中创建,但还有许多必须手动创建模型表之间的关系的情况。

如果您的模型中包含来自多个数据源的数据,则可能需要手动关系。 例如,您可以从关系数据源导入 Customers、CustomerDiscounts 和 Orders 表。 在源中的这些表之间存在的关系将在模型中自动创建。 然后,您可以添加来自不同源的其他表,例如,从 Microsoft Excel 工作簿中的 Geography 表导入区域数据。 然后,您可以手动在 Customers 表中的某一列和 Geography 表中的某一列之间创建关系。

若要手动在表格模型中创建关系,您可以使用关系图视图中的模型设计器或使用“管理关系”对话框。 关系图视图以图形格式显示表以及表之间的关系。 您可以单击一个表中的某一列,将该列拖放到其他表中以便轻松地在两个表之间以正确顺序创建关系。 “管理关系”对话框会以简单的表格式显示表之间的关系。 若要了解如何手动创建关系,请参阅 创建两个表之间的关系

Duplicate values and other errors

如果选择了在关系中不能使用的列,该列旁边将出现一个红色的 X。 您可以将光标暂停在错误图标之上,以查看提供有关该问题的详细信息的消息。 导致无法在所选列之间创建关系的问题包括:

问题或消息 解决方法
无法创建关系,因为这两个选定的列包含重复值。 若要创建有效的关系,您所选的一对列中应至少有一列必须包含唯一值。

您可以编辑列来删除重复值,也可以反转列的顺序,以便将包含唯一值的列用作 “相关查找列”
该列包含 Null 值或空值。 对于 Null 值,无法将数据列相互联接。 对于每一行,关系中所用的两列都必须具有值。

另请参阅

项目 说明
在两个表之间创建关系 介绍如何手动创建两个表之间的关系。
删除关系 描述如何删除关系和删除关系带来的后果。
双向交叉筛选器 描述相关表的双向交叉筛选。 如果两个表是相关的,且定义了双向交叉筛选器,则当跨第二个表关系查询时,可以使用第一个表关系的筛选上下文。