0

对于上下文,我有一个简单的 Azure SQL 数据库,我有一个具有 12 个维度的理论维度模型和一些最终应该用作 DWH 的事实表。

我希望在这个维度模型上应用历史化。开始简单并应用历史化的概念,我想在一维上启用它。在我的情况下,这是 DimEmployee,它看起来像这样,带有一行样本数据(它有更多列,但为简单起见,我只采用这些)

EmpKey 企业名称 空城 DWHDatStart DWHDatEnd 活跃
52 约翰 伦敦 2020 年 2 月 2 日 9999 年 12 月 31 日 是的

现在,如果假设 John 搬到另一个城市,我希望对此进行跟踪,以便 EmpCity 的值更新时所需的情况是

EmpKey 企业名称 空城 DWHDatStart DWHDatEnd 活跃
52 约翰 阿姆斯特丹 2021 年 8 月 6 日 9999 年 12 月 31 日 是的
52 约翰 伦敦 2020 年 2 月 2 日 2021 年 8 月 6 日 ñ

我将如何使用 TSQL 应用它。我认为它必须是某种触发器,但缺乏应用它的具体知识。我已经阅读过时态表,通常在启用数据历史化时,您会将历史数据存储在单独的历史表中。我认为由于这种模型设计,总是可以通过添加 DimEmployeeHist 尺寸或其他任何东西来扩展这个概念,但对于第一个概念,这不是必需的。我不知道在单独的表中执行此操作会带来什么价值,否则当您拥有大量历史记录时,您希望它们都整齐地存储在一个地方,以免弄乱您的主表。

这必须在创建表脚本中完成还是可以在创建表后完成?

4

1 回答 1

0

首先:忘记触发器。触发器不好

这是关于我通常如何执行此操作的脑筋急转弯。对此有很多排列,但这应该给你一个想法。

这是目标维度中的一行。当然还有很多其他的行

代理键 源密钥 源系统 企业名称 空城 DWHDatStart DWHDatEnd 活跃
3678 52 人力资源系统1 约翰 伦敦 2020-02-20 9999-12-31
3642 73 人力资源系统1 吉姆 布里斯班 2021-03-18 9999-12-31
  • SurrogateKey是连接到您的事实的键并且在维度表中是唯一的(并且应该使用约束或索引强制执行)
  • SourceKey是源系统中的key
  • SourceSystem是提供此记录的任何系统的代码。
  • SourceKey+SourceSystem是唯一的(并且应该使用约束或索引强制执行)

我们将数据加载到我们的数据仓库中。通常,第一步是将输入数据加载到临时表中。所以说我们在临时表中有这个:

EmpKey 企业名称 空城 ActiveRecordSurrogateKey 忽视
52 约翰 阿姆斯特丹 无效的 无效的
73 吉姆 布里斯班 无效的 无效的
7 杰克 德克萨斯州 无效的 无效的

ActiveRecord并且Ignore是工作列,它们不是来自源头。其他所有列确实来自源,但对维度一无所知

维度和临时表中显然会有很多记录。

首先排除维度中所有最新的记录。

UPDATE StagingTable
SET Ignore = 'Y'
FROM StagingTable TGT
INNER JOIN DimensionTable SRC
ON TGT.EmpKey = SRC.SourceKey
AND TGT.SourceKey = 'HRSystem1'
AND TGT.EmpName=SRC.EmpName 
AND TGT.EmpCity=SRC.EmpCity
AND SRC.IsActive = 'Y'

我们已经确定 Jim 没有改变,可以忽略

EmpKey 企业名称 空城 ActiveRecordSurrogateKey 忽视
52 约翰 阿姆斯特丹 无效的 无效的
73 吉姆 布里斯班 无效的
7 杰克 德克萨斯州 无效的 无效的

标识暂存表中在维度中已有活动记录但具有不同属性的所有记录

UPDATE StagingTable
SET ActiveRecordSurrogateKey = SRC.SurrogateKey
FROM StagingTable TGT
INNER JOIN DimensionTable SRC
ON TGT.EmpKey = SRC.SourceKey
AND TGT.SourceKey = 'HRSystem1'
AND TGT.IsActive='Y'
AND (TGT.EmpName<>SRC.EmpName OR TGT.EmpCity<>SRC.EmpCity)

(如果您愿意,这两个单独的更新可以合并为一个。)

现在我们的临时表看起来像这样。

EmpKey 企业名称 空城 ActiveRecordSurrogateKey 忽视
52 约翰 阿姆斯特丹 3678 无效的
73 吉姆 布里斯班 无效的
7 杰克 德克萨斯州 无效的 无效的

现在我们有足够的信息来更新维度。我们可以根据辅助列编写更多的 SQL 以应用于维度。

但首先,让我们指定一个固定日期。如果它在午夜之前和之后运行,这将阻止奇怪的事情发生。或者您可能希望以其他方式确定这一点,例如源中的输入参数或数据

DECLARE @Date DATE = GETDATE();

现在我们可以插入所有新记录(全新或更改)

-- This line inserts new dimension records:
INSERT INTO DimensionTable (SourceKey,SourceSystem,EmpName,EmpCity, StartDate,EndDate,IsActive)
SELECT EmpKey,'HRSystem1',EmpName,EmpCity, @Date,'2999-01-01','Y' 
FROM StagingTable 
WHERE Ignore IS NULL

现在我们的维度看起来像这样

代理键 源密钥 源系统 企业名称 空城 DWHDatStart DWHDatEnd 活跃
3678 52 人力资源系统1 约翰 伦敦 2020-02-20 9999-12-31
3642 73 人力资源系统1 吉姆 布里斯班 2021-03-18 9999-12-31
3693 7 人力资源系统1 杰克 德克萨斯州 2021-06-09 9999-12-31
3694 52 人力资源系统1 约翰 阿姆斯特丹 2021-06-09 9999-12-31

现在我们结束现有记录的日期:

-- This line end-dates existing records:
UPDATE DimensionTable
SET DWEndDate = @Date, Active = 'N'
FROM DimensionTable TGT
INNER JOIN StagingTable SRC
ON TGT.SurrogateKey  = ActiveRecordSurrogateKey
代理键 源密钥 源系统 企业名称 空城 DWHDatStart DWHDatEnd 活跃
3678 52 人力资源系统1 约翰 伦敦 2020-02-20 2021-06-09 ñ
3642 73 人力资源系统1 吉姆 布里斯班 2021-03-18 9999-12-31
3693 52 人力资源系统1 杰克 德克萨斯州 2021-06-09 9999-12-31
3694 52 人力资源系统1 约翰 阿姆斯特丹 2021-06-09 9999-12-31

因此,您基本上将所有这些 T-SQL 语句包装在一个存储过程中,添加一些事务、日志记录和错误处理。

CREATE PROC pUpdateDimPerson
AS
BEGIN

-- All the code above

END

存储过程比较源(暂存)和目标(维度)并做所有正确的事情。

还有很多其他的事情需要考虑,但这会给你一个想法。

于 2021-06-09T10:23:36.303 回答