如何建模列的可选细分

时间:2012-02-21 17:59:06

标签: database database-design olap

我想出一个数据库设计,允许对历史交易进行查询,我对这个特殊问题感到困惑。

要存储的其中一列是,比方说,每天的销售数量(按各种属性细分)。根据最近的数据,我们可以将其分解为在线和店内销售;但是,在某个截止日期之前,可用于填充此数据库的唯一信息是总销售数字,而没有细分。

我无法想到一种特别优雅的方式来呈现这一点,以便更新的数据可以填充逻辑“在线销售”和“店内销售”列,“总销售额”计算为其总和(在一个视图/细分/计算列) - 旧数据只能报告总销售数字。

此数据的FWIW客户将意识到销售明细可能存在或可能不存在 - 因此查询的输出始终具有有效的“总销售额”数字,并且可能缺少在线或店内的值销售。 (我特别说“缺失”而不是“空”,因为如果替代方案更有意义,没有强烈要求将其表示为此类。)

有没有规范的方法来处理这种情况?


鉴于到目前为止缺乏强烈的反应,我会发布一些我认为是候选人的答案(如果没有优秀的答案实现,我可能最终还是需要接受其中一个答案)。对这些的评论,批评和/或投票都得到了慷慨的接受 - 尤其是对它们的改进。

5 个答案:

答案 0 :(得分:1)

您所描述的是 OLTP OLAP 数据库之间的区别。

OLTP 在线交易处理)此类数据代表日常交易。例如,库存添加,更改删除。客户添加购物车请求,订单,退款。这些是整天发生的细节性交易。

OLAP 在线分析处理)此类数据表示在给定时间段内累积的数据。例如:每日,每周,每月,每季度,每年。购买将这些信息存储在一组单独的表格甚至数据库中,您可以运行不同的查询来为您提供所需的报告。

您可能遇到的问题是,当您拥有所有OLAP信息时,您需要OLAP信息。

如果您希望按单独的类别进行每日销售,则创建一组每日OLAP表,并且每晚运行一个单独的流程或一组流程,将这些数据存档到这些表中。

每个月您都可以运行不同的流程来创建每月OLAP表。

起初这是相当多的工作,但它给你两全其美。如果游戏整天都在针对您的OLAP数据进行游戏而不会影响客户或日常操作,则可以进行游戏。

答案 1 :(得分:0)

我可能会添加一个“销售版本”表,以便区分“历史性不易销售”和“新销售”。

所以,也许这种结构可以实现:

sales_version表

列:salesid,saleversion

sales_v1表

列:salesid,datetime

我认为对于每次销售,细节都在一个引用salesid的奴隶表中

sales_v2表

列:salesid,datetime,online,instore或者salesid,datetime,type('online'或'instore')或者本身引用销售类型表的类型ID。

我认为对于每次销售,细节都在一个引用salesid的奴隶表中

答案 2 :(得分:0)

一种方法是简单地将所有三列都存在于事实表中,并且它们都可以为空。对于较新的数据,仅填充两个更具体的销售数据列,对于旧数据,仅填充总销售额。

查询时,可以有条件地填充总销售额,例如:

CASE WHEN TotalSales IS NULL THEN OnlineSales + InStoreSales ELSE TotalSales END

从应用程序的角度来看,这具有最简单的优点。虽然从数据建模的角度来看,我不喜欢每个记录至少会留下一个字段为空的事实。并且很难表达 TotalSales被填充的数据完整性约束, OnlineSalesInStoreSales必须是填充。用触发器检查这个是否被视为良好做法?

(替代版本即使在新案例中填充TotalSales字段,但我认为可能不一致的数据的重复和风险值得稍微简单的查询。)

答案 3 :(得分:0)

另一种可能的方法是有两个不同的事实表,分别用于旧数据和新数据,并根据每种情况下确定的数据确定模型。

对于查询,总体结果将是来自两个事实表的数据的并集 - 来自旧事实表的选择用特定销售数据列填充NULL(或类似)。

这种方法很好,因为它可以准确地模拟我们正在记录的数据(并且能够记录),但如果两个表除了销售列之外是相同的,那么它可能会导致大量的字段重复。另外,我有一种(不合格的)感觉,当采用两个表的并集时,数据库很难用索引做有用的事情,这样查询性能可能会受到影响。

答案 4 :(得分:0)

第三种方法是将销售数据建模为与观察到的事实的多对一关系;也就是说,每个事实包含多个(可能只是一个)销售数字,每个数字都有特定类型。在这种情况下,总销售额只是存在的任何数字的总和。

因此架构可能看起来像

DataFact
-------------
DataFactId (PK)
(+any other fact columns apart from sales)

SalesData
---------
DataFactId (FK to DataFact)
SalesDataType ("Total"/"Online" etc - either as varchar or FK to dimension table)
SalesValue (the actual sales figure we want to record)

这种方法的优点在于它捕获了一个概念,即对于给定的事实,它可能包含也可能不包含任何特定的销售数据实体。它还抽象出变化的字段,这意味着任何公共字段仍然只在父DataFact表中表达一次(与separate fact tables不同)。如果将来还有额外的销售细分,那么扩展也是微不足道的。

缺点是它仍然没有表示必须存在总计或在线+店内的约束。实际上,我们甚至无法表达至少必须存在一个SalesData条目;这与添加多个可空字段的问题相同。虽然这种方法非常简洁,但为了充分利用其灵活性,我们希望将销售数据作为某种集合提供给查询客户端,这使得查询比标准2D结果集更复杂。它可以使用SalesData表上的聚合将 压缩回2D表中,但我相信你必须使用不同的约束多次拉它以确定每个字段。< / p>