开篇介绍
对于维度成员和事实数据直接的关系看到更多的可能还是一对一,一对多的关系。比方在事实维度(或退化维度)中一个订单和明细号组合而成的ID,对应的就是事实表中的一条数据,这就是一对一的关系。比方说在产品维度中,一个产品维度成员可能对应着多个事实数据成员,这就是一对多的关系。说简单点,就是事实表的外键引用了维度表的主键,形成了这种关系。
下面的这个例子就是一种多对多的情况,通常情况下,如果维度和度量值组中间是多对多的关系,那么在它们之间就需要创建一个中间事实表。 这个中间事实表的主键在数据仓库中可以不需要设计,包括与左侧维度表和右侧事实表之间的主外键关联也不需要设计,直接在数据源视图中修改逻辑关联就可以了 (在我的脚本代码中为了方便都主动的加上了主外键关联)。
如果要在 DimSalesReason 和 FactInternetSales 建立关联的话,那么就需要通过定义多对多关系来实现。
DimSalesReason - 销售原因维度,即每笔订单都会对应一个或者多个销售原因,比如因为价格原因和产品推广原因客户购买了,或者就是单单价格原因客户购买了。
类似于这种结构,我们一般可以这样来操作:
- 第一步:基于 DimSalesReason 维度表创建一个常规维度 Sales Reason。
- 第二步:基于 FactInternetSales 事实表创建一个事实维度 InternetSalesFact。
- 这样一来在定义维度用法时:
- 第三步:SalesReason 对度量值组 Internet Sales Reason (即FactInternetSalesReason) 将形成一种一对多的关系,常规用法。
- 第四步:InternetSalesFact 对度量值组 Internet Sales Reason (即FactInternetSalesReason) 将形成一种一对多的关系,常规用法。
- 第五步:InternetSalesFact 对度量值组 Internet Sales (即FactInternetSales)将形成一种一对多的关系,事实用法。注:广义上来讲,这里的一对多关系其实也包含了一对一的关系。
- 第六步,最后 Sales Reason 维度将借助于 度量值组 Internet Sales Reason 关系到事实维度 InternetSalesFact,并通过事实维度 InternetSalesFact 关联到度量值组 Internet Sales而形成一种多对多的关系。
第一步
首先还是先将 DimSalesReason 这个维度创建好。
第二步
添加一个事实维度,选择事实表 FactInternetSales。由于事实表并不存在类似于维度的 NameColumn 描述信息,并且这个事实表也非常的特殊,因为它是由 SalesOrderNumber 和 SalesOrderLineNumber 共同组成的主键列。由于相对而言 SalesOrderNumber 比 SalesOrderLineNumber 更有意义一些,这里选择 SalesOrderNumber 作为 Name Colum。
不需要与其它的维度进行关联。
不需要太多的属性,就留一个主 KEY 就可以了。
下一步并将维度名称命名为InternetSalesFact, 把 Fact 写在最后表示它是一个事实维度。
两个维度创建好了之后,保存并部署项目,同时修改 Cube 向 Cube 添加一个度量值组 - Fact Internet Sales Reason,这个维度只是一个中间维度。
可以隐藏 Fact Internet Sales Reason Count 度量值,因为实际上没有特别大的意义,讲它的 Visible 属性设置为 False。
一会将度量值组名称改为 - Internet Sales Reason。
保存并部署,然后编辑多维数据集的维度用法, 添加 SalesReason 维度后在 SalesReason 与 Internet Sales Reason 之间默认出现一个 Sales Reason。
第三步
SalesReason 对度量值组 Internet Sales Reason (即FactInternetSalesReason) 将形成一种一对多的关系,常规用法。
点击查看它们默认的关系,注意这里只是 SalesReason 维度和这个中间度量值组之间的关系,实际上 SalesReason 和 Internet Sales 之间是没有关联的。
在维度用法中添加新的维度即事实维度 InternetSalesFact,将表现第四步和第五步的行为。
第四步
InternetSalesFact 对度量值组 Internet Sales Reason (即FactInternetSalesReason) 将形成一种一对多的关系,常规用法。
第五步
InternetSalesFact 对度量值组 Internet Sales (即FactInternetSales)将形成一种一对多的关系,事实用法。
第六步
最后 Sales Reason 维度将借助于 度量值组 Internet Sales Reason 关系到事实维度 InternetSalesFact,并通过事实维度 InternetSalesFact 关联到度量值组 Internet Sales而形成一种多对多的关系。
可以看到 SalesReason 和 InternetSales 之间形成了多对多关系。
保存并部署,浏览一下 Cube 中的数据。可以看到订单号为 SO43697 的这笔订单有两个销售原因 - Manufacturer 和 Quality,虽然两个销售原因对应的销售额都是 3578美元,但是这仍然是属于一笔订单,因此看到销售类别 Other 的 Internet Sales Amount 还是显示的是 3578 美元。
数据库中的订单对应了两个销售原因,但它的销售额仍然是 3578.27 而不是 两个 SalesAmount的总和。
参看与本文相关的文章如下
SSAS 系列 - 多维数据集维度用法之一 引用维度 Referenced Dimension
SSAS 系列 - 多维数据集维度用法之二 事实维度(退化维度 Degenerate Dimension)
引起争论的结论
虽然这篇文章讲到了多对多维度的实现,但是实际开发中尽量避免使用这种关联关系,因为多对多的关系处理在数据聚合上效率肯定比通常一对一,一对多的效率要低很多。同时由于在建立多对多关系的时候需要额外创建一个事实维度来实现这种多对多的关联,因此额外的事实维度需要被创建,在维度处理上变得更复杂,个人建议在设计的时候应该尽量避免这种关系的出现。
PS
感谢各位在本贴的留言,回复与讨论。上面的这个结论下的有点不严谨,个人观点,希望不会误导大家,不过大家可以充分讨论。关于这个多对多的设计能否在某些场景下避免的问题,我保留我的意见,这个问题待续。
更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server) 如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。