如何使用维度中的代理键填充事实 table

How to populate fact table with Surrogate keys from dimensions

能否请您帮助了解如何使用维度中的代理键填充事实 table。

我有以下事实 table 和维度:

理赔事实

ContractDim_SK ClaimDim_SK AccountingDim_SK 索赔编号 索赔金额

ContractDim

ContractDim_SK (PK) 合约编号(BK) 报告期(BK) 代码 姓名

AccountingDim

事务编号(BK) 报告期(PK) 交易代码 货币代码 (这里要加ContractNbr吗??原来table在OLTP里有)

ClaimDim

CalimsDim_Sk(PK) CalimNbr (BK) 报告期(BK) 索赔说明 索赔名称 (这里要加ContractNbr吗??原来table在OLTP里有)

我将数据加载到事实 table 的逻辑如下:

  1. 首先我将数据加载到维度中(使用代理键创建为标识列)
  2. 从事务模型 (OLTP) 中,事实 table 将填充度量(ClaimNbr 和 ClaimAmount)

  3. 我不知道如何用 Dimensions 的 SK 填充事实 table,如何知道将我从维度拉到实际上的哪一行的密钥放在哪里 table(哪个键属于这个 claimNBR?) 我是否应该在所有维度中添加合同 Nbr 并在加载事实键时将它们连接在一起?

执行此操作的正确方法是什么? 请帮忙, 谢谢

通常的工作方式:

  1. 在您的维度中,您将拥有 "Natural Keys"(又名 "Business Keys")- 来自外部系统的密钥。例如,合同编号。然后为 table 创建合成(代理)键。
  2. 事实上table,所有键最初也必须是"Natural Keys"。例如,合同编号。您要连接到事实 table 的每个维度都必须存在此类键。有时,一个维度可能需要多个自然键(它们共同表示维度 table "Granularity" 级别)。例如,如果在 State-City 级别上建模,Location 可能需要 State 和 City 键。
  3. 将暗淡的 table 加入到自然键上的事实 table 中,并从结果中省略事实中的自然键和暗淡中的 select 代理键。我通常做一个左连接(fact left join dim),来控制不匹配的记录。我也一一加入暗淡(以更好地控制正在发生的事情)。

基本示例(使用T-SQL)。假设您有以下 2 tables:

Table OLTP.Sales
(   Contract_BK, 
    Amount, 
    Quanity)

Table Dim.Contract
(   Contract_SK,
    Contract_BK,
    Contract Type)

交换密钥:

SELECT
     c.Contract_SK
    ,s.Amount
    ,s.Quantity
INTO
    Fact.Sales
FROM
    OLTP.Sales s LEFT JOIN Dim.Contract c ON s.Contract_BK = c.Contract_BK

-- Test for missing keys
SELECT 
    * 
FROM 
    Fact.Sale 
WHERE 
    Contract_SK IS NULL

附带说明一下,我认为您的设计存在一些错误。

  • 报告期应该是一个单独的维度。通常它是一个具有所有 date/period 相关属性的日历 table。
  • 您当然不应该将 ContractNbr 添加到其他维度。您在合同维度中已有此数据。这就是星型模式的工作原理 - 合同属性始终可以通过事实 table 提供给您。无需复制它们。
  • 我不能肯定地说(没有足够的信息)但我怀疑 dim Accounting 和 dim Claim 可能设计不正确。如果您打算列出您的个人交易描述和个人索赔属性,那就错了。它将导致维度与事实 table 一样大。在一个好的设计中,事实 table 是 "tall and skinny",而维度是 "short and fat"。也就是说,事实上 table 你应该有很少的字段和很多记录,而在 dims 中有很多字段和很少的记录。通常,如果 dim 的记录数超过事实 table 记录的 10-20%,则表明设计不正确。正确处理这个问题的方法是将索赔分解成多个维度,并在您的事实table中留下索赔号(订单号、发票号、交易号等)作为"degenerate dimension"。这是一个高级主题,但您显然需要它来处理您的案例。重要的原因:如果你的维度和事实一样高 table,你的表现会越来越差。如果交易或索赔的数量在数百万条记录中,它可能会太慢以至于会扼杀你的设计。

如果您需要这方面的更多信息,我推荐这本书:

Star Schema The Complete Reference

[编辑以回答 follow-up 问题]:

我并不是要从 Claim 维度中删除 ClaimNbr 字段。我建议你根本不需要这样的维度。

这可能有点难以理解,但请考虑以下内容。 "Claim" 本质上是一个信息容器(与 "Invoice"、"Order" 等相同)。如果您将所有有用的数据片段移动到它们的相关维度,那么除了一个空容器之外什么也不会留下。

例如,假设您的 OLTP 索赔 table 包含以下字段:索赔编号、报告期间、索赔说明、索赔名称、合同编号、索赔金额。您可以按如下方式对它们进行建模:

  • 报告期:成为"Date"维度的业务关键
  • 合同编号:成为 "Contract" 维度的业务键
  • 索赔金额:保持事实 table 为数字 (fully-additive) 事实

剩下 3 个字段:索赔编号、索赔名称和索赔说明。此时,一些设计人员创建维度 "Claim" 并将这些字段放在那里。正如我之前提到的,这是一个错误,因为你将在你的维度中拥有与你的事实中一样多的记录 table,从而导致严重的问题。

更好的设计是在事实table中保留这些字段。索赔编号成为 "Degenerate dimension" - "empty" (non-existent) 维度的业务键。本质上,它只是一个信息容器的 ID,如发票号、订单号等。

Claim Name 和 Claim Description 也应该留在事实 table 中,成为 "non-numeric" (non-additive) 事实。如果你需要在报告中显示它们,这很容易做到,你可以对它们进行计数、对它们进行条件逻辑、测量它们的长度等。

另一种看待这个问题的方式:维度通常用于 "slice"(剖析)一些 attribute/field 的事实。例如,"Sale Amount by Country"、"Product Costs by Plant Location" 等。但是您不能按描述、注释或其他自由文本进行切片 - 这没有任何意义。

如果您的描述或其他声明属性是结构化的怎么办?例如,如果他们习惯于 categorize/classify 你的说法?在那种情况下,它们不是自由文本,它们是属于维度的属性。对于前mple,你可以设计维度"Claim Type"。或者 "Claim Status"。等等。如果这些小属性字段太多,您可以将它们组合成所谓的 "junk" 维度(又名 "Profile" 维度),即维度 "Claim Profile"。这样的设计简洁高效。

Read more on junk dimensions here