如何建模事实表

时间:2012-07-11 10:14:55

标签: sql-server database-design data-warehouse

我即将在星型模式中创建一个包含事实和维度的数据仓库。

我想回答的商业问题通常是:

  • 我们在第一季度卖出了多少钱?
  • 我们在第一季度向女性出售了多少钱?
  • 我们在第一季度向30-35岁之间的女性销售了多少钱?
  • 我们在第一季度为居住在纽约的30-35岁女性卖多少钱?
  • 我们在第一季度向居住在纽约的30-35岁女性销售了多少钱?

  • 我们去年在类别服装上卖多少钱?

  • 我们去年销售的蓝色牛仔裤多少钱?
  • 我们去年在澳大利亚生活的40-42岁之间的男性产品销售多少钱?

我在考虑一个日期维度,其粒度为一小时(指定年,月,日,小时,季度,日期名称,月份名称等) 我也在考虑产品维度和用户维度。

我想知道是否可以使用单个事实表来回答这些问题,或者是否适当创建多个事实表?我在考虑如下表:

FactSales

DimDate - fk到包含日期信息的表格(例如季度,星期几,年,月,日)

DimProduct - fk到包含产品信息的表,例如(产品名称)

DimUser - fk到包含用户信息的表格,如(年龄,性别)

TotalSales - 这些特定日期,产品和用户的所有销售额的总和。

另外,如果我想测量摊位的总销售额(金钱)和销售总数?创建一个具有相同尺寸但使用TotalNumberOfSales作为事实的新事实表是否合适?

感谢我能得到的所有输入。

2 个答案:

答案 0 :(得分:3)

我认为你走在正确的轨道上。上述所有问题都应该只使用一个覆盖销售的事实表来回答。

我认为应该开始一个非聚合,而是在需要时稍后聚合。考虑到一次销售可以包含多个产品和多个商品,我会按如下方式组织它...销售中每个产品的一个事实行(通常是发票上的行,所以我称之为“订单行”或“销售线“),也许三个柜台属性:

  • NumItems - 项目数量,即如果客户购买三件相同产品,则为3件。
  • NumLines - “订单行”的数量 - 应该始终为1.在以后聚合数据时可能很有用(大赢在SQL中已经有sum(NumLines)而不是count(*) ,或添加更正项目(NumLines = -1)。
  • NumSales - 一个小数,因此可以总计得出销售数量(如果销售涉及三种不同的产品,则包含三个订单行,则为0.333)。

现在,人们会得到一个问题,以获得正确的数量,即“涉及黑色衣服的销售数量”。我在之前的工作场所遇到过这个问题 - 我确信必须存在一些“最佳实践”,我们或多或少通过在事实表中引入SaleID(或TransactionID)来结束做count(distinct SaleID)。缺乏优雅,但有效。

在我们的设置中,我们有几个货币属性 - 最重要的是,一个用于收入(在支付销售物品的直接成本后剩下的收入)和一个用于营业额(客户支付的价格)项目)。销售税或增值税可能会增加更多复杂性。一个人可以只使用一个货币属性,然后将销售额分成事实表中的多行,但我想我宁愿在销售额事实表中推荐多个货币列。事实表中的所有内容都以“基础货币”(欧元,在我们的例子中)计算,然后我们有一个汇率维度来跟踪确切的金额。

我认为拥有包含一天中小时的日期维度是不合理的。在我之前的工作中,我把我的仓库保留在postgres中,而且我实际上管理得很好而没有日期维度 - 虽然日期维度被认为是“最佳商业实践”我发现在性能方面我们所有的目的都有更好的性能通过使用标准的postgres日期函数而不是在日期维度中拖动。我用它玩了很多,我想最终我发现最优化的是将日期和时间分成两个不同的属性。 (时区和夏令时给了我一些额外的麻烦......)

答案 1 :(得分:2)

我同意Tobixen - 你正走在正确的轨道上。

我建议您阅读Ralph Kimball的书" The Data Warehouse Toolkit",特别是关于零售销售的章节 - 它深入探讨了销售事实。

日期维度就像拥有日历表一样 - 您可以根据季度,会计月份以及日期特定于业务的其他事项进行拆分。我通常同时保留日期键和时间戳数据类型,因此我们可以使用财务日历执行操作。如果你需要把你的桌子放在那个级别,用一天几小时的桶或者几分钟等,我实际上会有一个单独的时间维度。我怀疑你需要每小时一次。

这就是我要做的事情:

声明你的事实表的粒度:

每个订单行1行

请注意,谷物不包含任何不能唯一标识该行的内容。

订单行的维度属性:

Date
Time (if needed, and bucketed by hour/minute etc)
Product
Customer

订单行的退化维度(这些是与交易相关的代码):

Order Number
Order Line Number

一些示例措施:

Item Price at time of Sale (optional, may be useful in some situations)
Discount Amount
Sale Dollars

这应该回答所有这些问题。

对于总计,过滤维度属性后的简单COUNT / SUM应该可以正常工作。

你应该考虑到客户维度是最难建立的模型之一,Kimball在他的书中将整整一章用于客户维度。