3

最近我一直在做一个项目,需要从 EDW 表中填充 Dim 表。

EDW 表属于 II 类,它确实保留了历史数据。在加载 Dim Table 时,其源可能是多个 EDW 表,也可能是具有多级透视(在属性上)的单个表。

平均值:将有 10 条记录 - 每个属性一个,需要在 domain_code 上进行旋转以在 Dim 中创建单行。在这 10 条记录中,会有一些属性具有相同的 domain_code 但具有不同的 sub_domain_code,这需要在子域代码上进一步旋转。

前任:

如果我得到域代码:01,02, 03 => 这是域代码的直接支点,我也会有域代码:10,子域代码/版本为 2006,2007,2008,2009

这意味着我需要将具有上述属性的源表拆分为两个 => 一个用于域代码,另一个用于 domain_code + 版本。

到目前为止,一切都很好。

在加载 Dim Table 时:

根据Dimensions的设计规范(最初由第三方编写),他们想要的是:

对于 EDW(属性)中的每一个更改,它应该组合所有相关记录(对于该 NK)意味着新的记录与其他当前的属性值 => 处理它们以创建新的暗淡记录并插入它。

这意味着如果单个提取包含更新的 100 条记录(每个 NK 一条),它应该组合 100 + (100*9) 条记录来插入/更新暗表。这种方法有多好。

我尝试做的其他方法是查找该 NK 的暗表,获取最近记录的值(未更改的属性)并将其插入并更新当前记录。

在源端为一个属性更改组装记录或查看暗表的最近记录并处理它的更好方法是什么。

如果这没有意义,想进一步阐述。

谢谢

这是桌子的模型

替代文字 http://img96.imageshack.us/img96/1203/modelzp.jpg

4

1 回答 1

2

看看这个例子

它应该相对简单。

它根据您的规则旋转基础数据。

它确定非规范化“行”的更改时间

它创建一个三角形连接来确定每个时期的开始和结束(我称之为快照)

然后它将这些窗口连接到基础数据以确定当时数据的状态(此时数据透视实际上已完成)

我认为您可能需要查看窗口机制 - 它返回正确的数据,但我不喜欢窗口重叠逻辑在我看来的方式 - 它并不小 - 我担心边界条件.

-- SO3014289

CREATE TABLE #src (
    key1 varchar(4) NOT NULL
    ,key2 varchar(3) NOT NULL
    ,key3 varchar(3) NOT NULL
    ,AttribCode int NOT NULL
    ,AttribSubCode varchar(2)
    ,Value varchar(10) NOT NULL
    ,[Start] date NOT NULL
    ,[End] date NOT NULL
)

INSERT INTO #src VALUES
('9750', 'C04', '789', 1, NULL, 'AAA', '1/1/2000', '12/31/9999')
,('9750', 'C04', '789', 2, NULL, 'BBB', '1/1/2000', '12/31/9999')
,('9750', 'C04', '789', 3, 'V1', 'XXXX', '1/1/2000', '12/31/9999')
,('9750', 'C04', '789', 3, 'V2', 'YYYY', '1/1/2000', '1/2/2000')
,('9750', 'C04', '789', 3, 'V2', 'YYYYY', '1/2/2000', '12/31/9999')

;WITH basedata AS (
    SELECT key1 + '-' + key2 + '-' + key3 AS NK
    ,CASE WHEN AttribCode = 1 THEN Value ELSE NULL END AS COL1
    ,CASE WHEN AttribCode = 2 THEN Value ELSE NULL END AS COL2
    ,CASE WHEN AttribCode = 3 AND AttribSubCode = 'V1' THEN Value ELSE NULL END AS COL3
    ,CASE WHEN AttribCode = 3 AND AttribSubCode = 'V2' THEN Value ELSE NULL END AS COL4
    ,[Start]
    ,[End]
    FROM #src
)
,ChangeTimes AS (
    SELECT NK, [Start] AS Dt
    FROM basedata
    UNION 
    SELECT NK, [End] AS Dt
    FROM basedata
)
,Snapshots as (
    SELECT s.NK, s.Dt AS [Start], MIN(e.Dt) AS [End]
    FROM ChangeTimes AS s
    INNER JOIN ChangeTimes AS e
        ON e.NK = s.NK
        AND e.Dt > s.Dt
    GROUP BY s.NK, s.Dt
)
SELECT Snapshots.NK
    ,MAX(COL1) AS COL1
    ,MAX(COL2) AS COL2
    ,MAX(COL3) AS COL3
    ,MAX(COL4) AS COL4
    ,Snapshots.[Start]
    ,Snapshots.[End]
FROM Snapshots
INNER JOIN basedata
    ON basedata.NK = Snapshots.NK
    AND NOT (basedata.[End] <= Snapshots.[Start] OR basedata.[Start] >= Snapshots.[End])
GROUP BY Snapshots.NK
    ,Snapshots.[Start]
    ,Snapshots.[End]
于 2010-06-18T17:29:34.387 回答