考虑到它具有一对多的关系 [Dim 1: many Fact],如何在星型模式中表示多值维度?

Posted

技术标签:

【中文标题】考虑到它具有一对多的关系 [Dim 1: many Fact],如何在星型模式中表示多值维度?【英文标题】:How can a multi-valued dimension be expressed in a star-schema given that it has 1-to-many relationship [Dim 1: many Fact]? 【发布时间】:2016-11-23 21:18:05 【问题描述】:

我是数据仓库实践的新手,在学术练习的背景下,我想使用所选感兴趣领域的数据集创建星型模式。所以,我和我的同学选择了一个国家一年内发生车祸的数据集。

问题是在很多情况下,即使不是最多,也涉及不止一辆汽车。因此,如果我选择将“事故”事件作为事实表,以“驾驶员”、“汽车”、“伤亡”、“位置”、“连续”等作为维度,如何将这些事件转换为星型模式,当维度“汽车”、“司机”和“伤亡”是多值的?例如,我可以涉及 3 辆汽车、3 名司机和 7 名伤亡人员。考虑到使用星型模式是强制性的。

此外,据我所知,事实表通常可以在测量中包含数值。它也可以有分类变量作为测量值吗?

【问题讨论】:

一种方法是认识到这还有另一个维度——“崩溃”维度。因此,有 5 辆汽车的碰撞会得到 5 行,它们都指向同一个单一维度记录(每次碰撞都会创建一个新记录)。这是在星型模式中对标头详细信息进行建模的一种方法,而不会违反星型模式的理念。您正在合理地建模“崩溃”,因此可以使用崩溃周围的属性来获得它自己的维度。您甚至可以说崩溃维度可以在崩溃级别连接到另一个更高级别的事实。 另一种建模方法是使用桥接表,这是一些(不是所有)报告工具可以用来停止重复计算的结构。 kimballgroup.com/2012/02/design-tip-142-building-bridges 感谢您的回复!因此,如果我理解正确,您建议我将“事故”事实表转换为维度表,并将仅由维度的外键组成的表作为事实? 这是一种看待它的方式,是的。那么你的事实将被称为参与者。最好尝试一些事情并进行实验。 如果这是英国事故数据集,我建议按照数据的自然粒度(即下载中提供的)坚持粒度并放入桥接表。它有效,并且会让你在学术练习中做的工作要少得多。桥牌并不邪恶。 【参考方案1】:

维度建模中一个非常重要的概念是晶粒。 Ralph Kimball(如果您正在学习维度建模,您会一次又一次地遇到他的工作)强调从尽可能低的粒度进行建模非常重要。这可以让您以尽可能多的方式对数据进行切片和切块,从最低粒度到更高粒度进行汇总。

当您发现其中一个问题似乎都是多对多时,问题实际上是您为相关事实表选择了错误的粒度。向 Nick.McDermaid 道歉(他建议在 cmets 中进行这种粒度更改),“个人参与事故”的粒度低于“事故”,因此将事实表的粒度至少降低到该级别 - 并且创建一个事故维度 - 很有意义。

不过,这可能不是最低粒度;例如,如果您的数据集跟踪受伤情况,则每个参与者可能都有多处受伤。因此,在这种情况下,事实表粒度可能会更好地作为“在事故中遭受的伤害”——您需要在“伤害”维度中显示“无伤害”的行,以防万一,以包括那些没有受伤的参与者。所以你应该做的第一件事不是决定你的事实表是什么,而是筛选数据并试图找出你的最低粒度是多少;完成此操作后,您应该能够很好地掌握事实表的建模对象以及需要哪些维度。

维度建模可能有点难以破解,因为您可以通过多种方式来做事 - 而最正确的方式通常看起来并不明显,尤其是当您从您所在的背景中移动时重新习惯于更规范化的数据结构。我建议首先尝试使用最基本的表格类型来建模一些东西——即尽量避免雪花、桥表等东西——看看你是否能想出一个避免这些技巧的解决方案。这通常会导致更好的模型(即更易于导航、具有更好的查询性能并且可用于回答更多问题的模型)。

Nick.McDermaid 对尝试不同事物的建议也很可靠,因为它可以帮助您摆脱最初的假设。有时有多种潜在的设计 - 可能需要彻底考虑它们才能决定哪个是最好的。

【讨论】:

【参考方案2】:

我不得不在我的公司为这个东西建模。

事件和车辆各有特色。您需要 FactIncident 和 FactIncidentVehicle。这允许您关联与事件相关的属性(日期、位置、类型)以及事件中每个车辆的属性。

Incident 维度几乎是一个退化维度,仅包含一些具有 IncidentID 的属性,例如警方报告编号。

“事故车辆”维度也只有一些特定于该事故车辆的属性,例如车辆是否被拖走。如果您的数据允许非车辆事故(例如绊倒和跌倒),则您的维度中需要“无车辆”车辆记录以及“未知”车辆。

事件车辆人员是捕获此特定事件的人员与车辆之间关系的另一种方法。垃圾维度对于保存 flag(Y,N,Unk) 问题很有用,例如受伤、引用、所有者、司机等。

这种方法效果很好,它允许一个事件有 0 到许多车辆和 1 到许多人,并且允许同一个人和/或车辆成为多个事件的一部分(用于车队/员工记录)。

【讨论】:

【参考方案3】:

最常见的方法是使用桥接表http://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/multivalued-dimension-bridge-table/

【讨论】:

桥接表不一定是这个问题的答案。 Kimball Group 对桥接表的看法:“同样,如果您的设计充满了桥接表来捕获多值维度关系,则您需要回到绘图板上。您可能对事实表的粒度有问题。 " (kimballgroup.com/2003/10/fistful-of-flaws) 我们还可以引用 Kimball Group 的话说,桥牌桌正是您在这种情况下使用的。您通常可以选择更改事实的天然纹理或放入桥接表中。桥牌桌往往是两害相权取其轻,而这里似乎确实如此。 @Rich The Kimball Group 肯定说他们是一个选项,但他们非常强调他们不是这些情况的唯一解决方案,不应该被对待在所有情况下都使用默认解决方案。他们没有说您应该选择它们而不是其他解决方案,只是您应该在决定最适合您的特定场景之前考虑所有选项。说桥牌表是解决方案,只需要这么少的信息就下结论还为时过早。 请参阅kimballgroup.com/2014/05/… 和kimballgroup.com/2008/09/… 了解更多信息。引用第一条:“多对多关系通常在事实表中得到最好的解决。” 我不认为该答案的选择性引用和降级是有用的 - 当所有评论者所做的只是将它们指向桥梁时,看起来桥梁不是答案或通常应该避免最常见的方法(正确)。解决此问题的桥梁不会使解决方案“充满桥梁”,这是 Kimball Group 的点,您将重新考虑您的事实。同样,您引用的文章中的其他引用也强调了桥梁的好处。

以上是关于考虑到它具有一对多的关系 [Dim 1: many Fact],如何在星型模式中表示多值维度?的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试使用实体框架进行急切加载,其中我在区域和客户端之间具有一对多的关系

CoreData:查询一对多对多的关系

Hibernate关系映射之many-to-many(多对多)

django之跨表查询及添加记录

事实和维度表:一对一的关系

one2many,many2one,many2many映射