当前位置: 资源下载\BI 原创\设计技巧(一)—— 使用MERGE语句进行渐变维处理

设计技巧(一)—— 使用MERGE语句进行渐变维处理
 

作者:Warren Thornthwaite

译者:Daniel Zhen 
 

很多ETL工具都提供了处理渐变维度的功能。也有些情况下,当此类工具不能满足需求时,ETL开发者将直接面对数据库,验证更新或变化了的行,并恰当的使用INSERT和UPDATE命令处理之。在“深入数据仓库生命周期”课程上,我已经演示了使用INSERT和UPDATE语句的代码。几个月后,我的朋友Stuart Ozer告诉我,使用SQL Server 2008中的MERGE语句在代码执行方面有更好的效率。他所引用的是MSSQLTips.com上Chad Boyd的Blog,这给了我一些如何实现的启示。MERGE是INSERT,UPDATE和DELETE的组合,它有效的降低了语句的复杂度。

本例处理的是简单的客户维度,它具有两个属性:first name和last name。我们将把first name作为类型1处理,把last name看作类型二处理。记住,所谓类型1是指维度属性的旧值覆写;类型二是通过增加新值让跟踪历史纪录更具效率。

步骤1: 覆写类中的变化值

我曾尝试在整个例子中只使用一次MERGE语句,但该函数属于确定性函数,每次只能执行一次update语句,所以我在下例中分别使用了多个MERGE进行类型1更新。因为类型1定义为更新,所以也可以使用update语句直接处理。

MERGE INTO dbo.Customer_Master AS CM
USING Customer_Source AS CS
ON (CM.Source_Cust_ID = CS.Source_Cust_ID)
WHEN MATCHED AND --根据类型1更新所有已存在的行
CM.First_Name <> CS.First_Name
THEN UPDATE SET CM.First_Name = CS.First_Name

以上简版的MERGE语句,通过关联业务键,更新所有主表和原表中First_Name不一致的行,实现了Customer_Source表和Customer_Master维度的归并。

步骤 2: 处理类型2中的变化值

现在我们将使用另一个MERGE语句来处理类型2中的变化值。这是件比较棘手的事,因为在跟踪类型2变化值是会有很多的步骤。执行我们代码将需要:
1. 在截止时间前,适当并有效地插入新客户数据行。
2. 通过设置恰当的终止时间和设置current_row flag = ‘n’,标识类型2中维度属性变化的行。
3. 通过设置恰当的终止时间和设置current_row flag = ‘y’,插入类型2的变化行。
这样做会导致太多的步骤需要MERGE处理的问题。幸运的是,MERGE可以流化输出到下一个过程。我们将使用这一功能,使用SELECT从MERGE的结果中选择行并插入到Customer_Master表中,最终完成类型2变化行的插入。听上去,这是一种复杂的并容易出问题的方法,但是它的好处在在于可以一次性找到类型2中变化了的行,并可以多次使用。
代码以INSERT和SELECT语句开始,用来在MERGE语句执行后处理变化行插入。之所以把它们放在前面,是因为MERGE是包含在INSERT嵌套中的。代码中包含很多对于当前日期的引用,代码中假设变化自昨天起有效(getdate()-1),即前天(getdate()-2)的数据可以被标识为退化。最后,我列出了代码,并根据行号进行说明:

1 INSERT INTO Customer_Master
2 SELECT Source_Cust_ID, First_Name, Last_Name, Eff_Date, End_Date, Current_Flag
3 FROM
4 ( MERGE Customer_Master CM
5 USING Customer_Source CS
6 ON (CM.Source_Cust_ID = CS.Source_Cust_ID)
7 WHEN NOT MATCHED THEN
8 INSERT VALUES (CS.Source_Cust_ID, CS.First_Name, CS.Last_Name,
convert(char(10), getdate()-1, 101), '12/31/2199', 'y')
9 WHEN MATCHED AND CM.Current_Flag = 'y'
10 AND (CM.Last_Name <> CS.Last_Name ) THEN
11 UPDATE SET CM.Current_Flag = 'n', CM.End_date = convert(char(10), getdate()-2, 101)
12 OUTPUT $Action Action_Out, CS.Source_Cust_ID, CS.First_Name, CS.Last_Name,
convert(char(10), getdate()-1, 101) Eff_Date, '12/31/2199' End_Date, 'y'Current_Flag
13 ) AS MERGE_OUT
14 WHERE MERGE_OUT.Action_Out = 'UPDATE';

代码注释

    •   1-3行执行典型的INSERT语句. 将用来在最后插入类型2的变化行。
    •   4-6行执行MERGE,装载Customer_Source数据进入Customer_Master维度表。
    •   第7行说明如果无法匹配业务键,我们必须有一个新的客户数据加入,因此第8行执行了插入操作。你可以通过参数化有
       效日期取代假设的昨天的日期。
    •   9-10行定义了业务键可以进行匹配的行的子集,特别是,Customer_Master表中已有数据和类型2中数据不同的行记录。
    •   第11行通过设置的结束日期和把当前行标志设置为“n”,实现了当前行的退化。。
    •   第14行限制了Customer_Master中需要更新的行,虽然相关退化的行已经在第11行进行了处理,但是我们是从第12行从Customer_Source表中输出了当前值。

总结:
MERGE语句最大的优势在于,一个数据集可以被多次处理,而不是多次请求分别处理插入和更新操作。优秀的性能优化专家会用到这一非常有效的方法。

原文链接:http://www.dwway.com/?uid-42816-action-viewspace-itemid-6338

 

译者介绍:

甄浩,北京迈思奇BI开发工程师,资深BI咨询顾问,软件工程专业硕士。

主攻数据仓库、OLAP建模、数据挖掘、企业绩效管理等技术领域,具有6年的BI项目实施和咨询经验。

 

北京迈思奇科技有限公司 2004-2008 地址:北京市海淀区中关村紫金数码园4号楼201,邮编 100190 电话:86-010-62662626 传真:86-010-62662776 京ICP备05066245号