hqt*_*hqt 4 data-warehouse database-design star-schema
从生产数据库构建DW星型模式设计的步骤/规则是什么?具体来说,您如何处理多对多关系。
我了解如何获取包括多对多关系在内的基本数据,并获得规范化的生产数据库:
例如:
如果我想处理销售交易,给表Product Entity,Promotion和Employee中,第一步是建立一个表,SaleTransaction:
SaleTransaction
- TransactionID
- ProductID
- EmployeeID
- SellingDateID
- Quantity
- SaleAmount
- PromotionID
Run Code Online (Sandbox Code Playgroud)
该Promotion实体将是:
Promotion
- PromotionID
- ProductID
- DiscountAmount
Run Code Online (Sandbox Code Playgroud)
但是,这将只允许每次销售交易 1 个产品和 1 个促销活动。由于我们希望允许一种或多种产品以及零个或多个促销:
我删除PromotionID,ProductID,Quantity,和(除非因某些业务规则)SaleAmount从SaleTransaction
我创建SaleTransactionDetail:
- DetailID
- TransactionID
- ProductID
- Quantity
- SaleAmount
Run Code Online (Sandbox Code Playgroud)我会创造SaleTransactionPromotion:
- TransPromoID
- PromotionID
Run Code Online (Sandbox Code Playgroud)将生产 DB 设计转换为 DW 星型模式设计的等效步骤是什么?
多对多表通常使用“桥接表”处理。这实际上只是您在事务数据库中使用的多对多表的另一个名称:一列用于第一个表的 FK,一列用于第二个表的 FK,可能还有一两列用于家政领域。
您可能还需要Weight桥接表中的一个字段,其值等于 1 除以每次销售的条目数。当您想要避免重复计算具有多个促销活动的订单时,这让我们计算SUM(Weight)而不是COUNT(*)。
你提出的模式很好,但我认为它可以稍微改进;想到两件事。其中之一是,我一般会崩溃SalesTransactions,并SalesTransactionDetails到一个表。这为客户 ID 之类的东西引入了冗余,这应该会让您的 OLTP 直觉退缩(从规范化数据库过渡到数据仓库是一种范式转变!),但在这种情况下,这是值得的。通过将您的所有销售额放入一个表中,您可以简化连接,并且在许多数据库中表明您想要使用位图索引。在仓库中,您通常最终不得不进行表扫描,但这没关系,因为您的事实表非常窄,并且适合内存。
所以我们有三个表Sales,Promotions, 和SalesPromotions。您可能会考虑“订单”而不是“销售”,因为后者意味着可能不适用的最终确定性。如果您的系统包含已下达但未发货或未关闭的订单,则更通用的术语更有意义。这是在狡辩,但仔细考虑你给事物命名的东西从来没有坏处。
CREATE TABLE Orders
-- IDs/dimensions:
OrderID
EmployeeID
ProductID
-- Date dimensions: date placed, date contract signed, date shipped, etc.
-- Metrics: quantity, gross price, net price, extended price
-- Attributes: is taxable, currency code, business key
CREATE TABLE Promotions
PromotionID
-- Date dimensions: date effective, date expires
-- Metrics: fixed amount, percentage amount
-- Attributes: name, type
CREATE TABLE OrderPromotions
OrderID
PromotionID
Weight
Run Code Online (Sandbox Code Playgroud)
ExtendedPrice可以是计算列而不是存储值。如果属性开始使您的Orders表膨胀,请考虑使用“垃圾维度”。
您可以包含ProductID在 中Promotions,但前提是促销只适用于单个产品。例如,您是否有一些适用于整个订单而不是特定订单项的促销活动?促销是否适用于今天的产品代码 ABC1,但明天在价格更改后适用于产品代码 ABC2?
我想到的第二个警告是 ID。我强烈建议您在数据仓库中使用合成密钥 (SK),而不是依赖来自源系统的 ID。有很多原因,这在 DBA.StackExchange 上的其他地方进行了讨论,但随意:
Customers.FirstOrderSK对于没有订单的客户,该字段将填充 -1,对于有订单但尚无更多具体信息的客户,字段将填充 0。您的报告可以反映这一点,而无需放入特殊逻辑来处理 NULL 值。您可以通过为没有促销的订单添加“虚拟记录”来利用桥表中的合成键。用PromotionID-1填充它,表示没有应用促销;现在,您的数据的消费者可以过滤以全价出售的订单。