最近我一直致力于项目,需要从EDW表中填充Dim Tables。
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 + version。
到目前为止一切顺利。加载Dim Table:
根据Dimensions的设计规范(最初由第三方编写),他们想要的是:
对于EDW(属性)中的每一个变化,它应该汇集所有相关记录(对于那个NK)意味着新的一个具有其他属性值,即current =>处理它们以创建一个新的暗淡记录并插入它。
这意味着如果单个提取包含更新的100个记录(每个NK一个),它应该组装100 +(100 * 9)个记录以插入/更新dim表。这种方法有多好。
我试图做的其他方法就是查看dim表,查找NK获取最近记录的值(未更改的属性)并插入并更新当前记录。
对于一个属性更改或查看昏暗表的最近记录并处理它,在源端汇编记录的更好方法是什么。
如果这没有意义,想进一步详细说明。
由于
这是表格的模型
答案 0 :(得分:1)
查看this example。
应该相对简单。
根据您的规则调整基础数据。
它确定非规范化“行”的更改时间
它创建一个三角形连接来确定每个时期的开始和结束(我称之为快照)
然后它将这些窗口连接到基础数据,以确定当时数据的状态(此时枢轴实际已完成)
我认为您可能需要查看窗口机制 - 它返回正确的数据,但我不喜欢窗口重叠逻辑对我的看法 - 它不是很小 - 我很担心边界条件。
-- 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]