聚合表来处理事实表中的distinct-count

时间:2014-08-06 21:50:20

标签: olap mondrian

我正在构建人力资源OLAP架构,而且我在计算员工人数方面遇到了很多麻烦。这听起来很简单,但在OLAP事实表设计和处理不同的员工之后,它实际上非常棘手。基本上我遵循Ralph Kimball列出的以下模型。我有一个Employee表,表示对员工执行的事务,然后我有一个Employment表,它是事实表。

在Ralph的例子中,他只按月计算事实表(即month_key),但在我的表中我可以按月,季度,年等计算。在月份级别一切正常因为单个员工没有重复的条目。但是,将层次结构向上移动到四分之一年或一年,并且单个员工得到双重计数或更多。例如,如果员工在12个月内就业,如果你总结他的记录,他将被计算12年!

问题在于,由于这些重复的条目,您无法汇总表中的数字。我已经尝试了其他几种方法,但它们都没有真正可靠地工作。但我想到了这一点,并认为我可以在就业日期为每个级别创建汇总表。一个表用于一年,一个表用于宿舍等。这样我的加载程序可以决定如何计算每个级别的员工,并确保只汇集一个员工。我的数据逻辑结构保持不变。从查询的角度来看,我仍然可以在几年,几个月,几个月等时间里考虑我的数据。

这是聚合表的适当用法吗?我从来没有听说有人为此目的使用它们。我没有使用它来提升性能,但是我使用它来规范化数据并确保所有内容都以可以聚合的方式加载而不用担心重复。我的疑问不会改变他们吗?我仍然可以做类似的事情:

在ROWS上选择[工作地点],[措施]。[就业]栏目中的[人数] [就业日期] [2014]

在ROWS上选择[工作地点],[措施]。[职位]在[就业]的栏目中[就业日期]。[2014]。[5]

Mondrian将使用适当的表来提取数据,而不必在查询中指定它。

1 个答案:

答案 0 :(得分:3)

不同的计数是一个充满问题的世界。不惜一切代价避免它。

问题1:从some_table"做一个" select count(distinct some_column)很慢;

问题2:不同的计数不会聚合,这意味着您无法在某个详细级别获取总计并将它们组合在一起以获得另一个级别的总计。因此,您无法选择最近的聚合表",您需要选择"确切的聚合表"。因此,有两件事情发生:

  • 每个层次结构的每个组合都需要1个聚合表
  • 缺少一个或多个agg表意味着Mondrian需要直接从事实表中获取数据。

在您的情况下,这意味着如果您有公司 - 部门 - 团队和日期 - 季度 - 月 - 月级,您将需要:

  • 公司/所有和日期/年级的汇总表
  • 公司/所有和日期/季度级别的汇总表
  • 公司/所有和日期/月级的汇总表
  • 3,现在在部门层面
  • 团队层面的3个以上

随着更多维度,事情变得更糟,你最终可能会有数百个聚合表。

更糟糕的是,没有办法强迫蒙德里安选择聚合表A或B.它会以半晦涩的方式选择一个(或不是),用户很少或根本没有控制。 / p>

另外,必须进行不同的计数以构建聚合表意味着您的聚合脚本将非常慢。

一些替代方案:

  1. 请勿对该指标使用聚合。面对这样一个事实:无论如何,这些不同的计数都需要来自事实表;
  2. 构建快照事实表,其中包含月份到日期,季度到日期和年初至今的唯一计数,作为3个单独的列。有你的"快照"将date作为具有hasAll = false的层次结构并跳过所有级别,以便您选择日期或什么也看不到(因为您无法在快照之间聚合);
  3. 尽量避免以某种方式做一个明确的计数。一种可能的方法是跟踪自ETL"最后一次见到此人以来的天数,您可以通过查找来实现。你可以说,一个月的人数是(一个月的第1天看到的人)+(第2天用"上次见过的人数"> = 2)的总和+(人们在第3天看到"自上次见过以来的日子"> = 3)+ ... +(第30天用#34;自上次见过以后的日子"> = 30)。
  4. 方法1具有更简单的明显优势,但缺点是将所有复杂性推迟到DB本身; 方法2的优点是可以快速显示所需的所有值,但代价是进一步的ETL工作,并且仅限于您添加的措施,不允许任何灵活性; 方法3是最灵活的,但是以ETL工作的显着增加和更复杂的查询为代价。

    哪一个是正确的方法?坦率地说,没有一个。解决星形模式和蒙德里安问题是一个非常棘手的问题。