员工 0HR_PA_0 业务数据源中有一个CALMONTH日历年/月的字段,只要员工还在职,每个员工每个月都会产生一条数据:
人事事件 0HR_PA_1 业务数据源中有一个CALDAY日历天的字段,只要员工发生人事事件(如入职、晋升、调离、离职等),该数据源中就会产生一条数据:
需求:将 0HR_PA_0 、0HR_PA_1 两个数据源中的数据抽到DSO后,需要在原有的数据字段上附加上 人事子范围 、公司代码、员工组 、员工子组、人事范围、雇佣状态 、组织单位、业务范围 这些数据字段(从上面图中可以看到这两个业务数据源中原本没有这些字段),即需要将主数据属性直接存入到交易数据中(而非导航属性那样,主数据属性是通过导航的方式关联起来,而这里是要求将这些主数据属性直接存储到Fact表的维度表中,即要求以场景A来建模,场景A具体应用及实现请参照另一篇文章
),如何用场景A来实现?
分析:现需要将业务数据源中原本没有的这些字段附加到业务数据上,除了通过直接对业务数据源进行增强外,针对这两个业务数据源( 0HR_PA_0 、0HR_PA_1 ),有更简便的方法就是在DSO层,通过 Read Master Data 读取主数据转换规则 将这些附加字段数据从相应主数据中读取出来(前提是附加的这些字段是交易数据能关联到的主数据属性字段, 如这里附加的这些字段,都是可以通过0HR_PA_0 、0HR_PA_1业务数据源与员工0EMPLOYEE、组织0ORGUNIT关联得到的,但增强方式没有这个要求)。由于 人事子范围 、公司代码、员工组 、员工子组、人事范围、雇佣状态 、组织单位 这些字段是InfoObect员工OEMPLOYEE的属性(且这些属性与时间相关):
而 业务范围 又是 组织单位 0ORGUNIT信息对象 的属性(且也与时间相关):
现在要附加上的这些字段分别属于 OEMPLOYEE( 人事子范围 、公司代码、员工组 、员工子组、人事范围、雇佣状态 、组织单位) 、 0ORGUNIT(业务范围)这两个信息对象中,并且 业务范围 这个字段需要在 组织单位 属性抓出来后,才能根据组织单位到 0ORGUNIT信息对象 中将 业务范围 属性抓出来。下面屡一下这些附加字段的抓取顺序:先将业务数据源0HR_PA_0 、0HR_PA_1的数据抽取到第一层DSO中(明细层,原样存储数据源的数据,在这一层不会增加数据源抽取结构以外的字段);再将第一层DSO数据转换存储到第二层DSO中,第二层DSO需在第一层DSO的基本上,附加上 人事子范围 、公司代码、员工组 、员工子组、人事范围、雇佣状态 、组织单位 这些字段,这些字段通过 Read Master Data 转换规则从主数据OEMPLOYEE中抓取出来,但要注意的是这些属性是与时间相关的,读取时需要加上业务时间这一条件(即从0EMPLOYEE底表里抓取这些属性字段时,除了员工编号外,还需要加上 业务时间0CALMONTH 条件);最后第三层DSO在第二层的基本上再附加上业务范围 这一字段,此时需从 0ORGUNIT信息对象 底表抓取,条件是 组织单位 + 业务时间0CALDAY。下面以 员工0HR_PA_0 数据源为例,采用三层DSO建模:
具体转换规则如下:
上面在通过 Read Master Data 读取主数据 转换规则读取主属性时,由于主属性是时间相关的,则读取主数据的时间条件取值可以是以下三种:
当前日期:读取主属性时,会以当前时间点(YYYYMMDD)为时间限制条件值,抓取当前时间点所对应有效属性,即抓取满足 DateFrom <= 当前时间 <=DateTo 时间条件的主数据( DateFrom 、 DateTo为主数据底表两个字段,用它们来表示数据的有效期)
常数日期:以某个常数日期(也是YYYYMMDD,到天)为时间条件,读取相应时间点的有效主属性
Form(从):以DSO源中的某个日期字段(上面选择的为0CALMONTH,该字段为源DSO中的某个时间字段,只到月)为时间条件,读取相应时间点的主属性。由于这里选择的日期字段0CALMONTH只到月,以此为时间限制条件(DateFrom <= 0CALMONTH <=DateTo )去主数据底表里查询时,可能会有多条数据对应,这时是取最早的,还是最晚的数据(但不能取到中间某个时间段主数据),就要看选择的是“开始”还是“结束”了,选择的不同,抓取到的主属性也是不一样的,具体请看下面的测试:
员工 0HR_PA_0 业务数据源 中的日历年月CALMONTH只到月,以此字段作为业务产生的时间来读取时间相关的主数据属性时,”开始“、”结束“测试结果如下:
人事事件 0HR_PA_1 业务数据源 中的日历天CALDAY与上面区别在于精确到天了,所以不管选择”开始“还是”结束“,同一业务数据所抓取到的主数据结果是一样的:
所以从上面两组(0HR_PA_0、0HR_PA_1)测试结果来看,”开始“、”结束“只对到月(或季度、年)业务时间起作用,如员工0HR_PA_0数据源的0CALMOTH业务时间字段;对已精确到天的业务时间不起作用,如人事事件0HR_PA_1数据源的0CALDAY业务时间字段,到天时不管选择的是“开始”还是“结束”读取到的主数据属性都是一样的,因为已精确到某一天,所以读取到的主数据有且仅有一条;
根据不到天(如只到月、季度、年)的业务时间来抓取时间相关主数据时, Read Master Data 中选择“开始”时,如果有多条符合(原因就是业务时间没有精确到天,而主数据的DATEFrom与DAETo是到天的,在以业务时间为条件从主数据底表读取主属性时,会忽略掉主数据有效时间字段DATEFrom与DAETo中的天,这样就会匹配到多条主数据),就取有效时间段最早的那条;如果选择“结束”时,有多条符合就取最晚(最新的)的那一条,注:不可能只取中间某个时间的主数据
上面实例是以员工0HR_PA_0数据源为例,演示了如何通过 Read Master Data 转换规则 读取时间相关的主数据,并且是通过三层DSO建模来实现的,实质上也可以只通过两层DSO就可以实现OEMPLOYEE与 0ORGUNIT主数据的读取。具体实现方式:需要在第一层DSO的End Routine中,先根据数据源中的员工编号从OEMPLOYEE信息对象底表中 将 组织单位 抓取出来(注:通过End Routine程序抓取主数据时,也需要考虑时间相关,End Routine程序代码中需加上时间限制条件),然后在第二层DSO的转换规则中,通过 Read Master Data 方式将将所有的附加字段一次性全读取出来,而不需要分两层DSO分两次读取OEMPLOYEE与 0ORGUNIT主数据。注:上面员工0HR_PA_0数据源不能采用这种 End Routine + Read Master Data 的两层DSO方式,因为业务时间只到月,虽然程序可以读取时间相关的主数据,但程序无法灵活实现“开始”与“结束”,只有人事事件0HR_PA_1数据可以使用 End Routine + Read Master Data 的两层DSO方式建模,因为相应业务时间到天了,可通过End Routine精确读取到一条时间相关的主数据,与“开始”“结束”无关。下面采用这种End Routine + Read Master Data只有两层DSO方式来建模:
0ORGUNIT抓取是通过End Routine实现的,但要注意的是,0ORGUNIT的抓取虽然是放在End Routine代码里实现的,不需要划线,但规则类型也不能选择“无转换”,否则DSO 激活时,New表里抓取到的 组织单位 在激活后Active表里的组织单位就会丢失,所以最好选择规则类型为常数转换规则,值为空,这样在激活后就不会消失),具体代码如下:
METHOD end_routine.
*=== Segments ===
FIELD-SYMBOLS:
<RESULT_FIELDS> TYPE _ty_s_TG_1.
DATA:
MONITOR_REC TYPE rstmonitor.
*$*$ begin of routine - insert your code only below this line *-*
... "insert your code here
*-- fill table "MONITOR" with values of structure "MONITOR_REC"
*- to make monitor entries
... "to cancel the update process
* raise exception type CX_RSROUT_ABORT.
DATA:t_docinfo TYPE TABLE OF _ty_s_TG_1.
DATA:wa_docinfo TYPE _ty_s_TG_1.
**=======调试使用
Data: t_zjzjtest TYPE TABLE OF zjzjtest .
DATA wa_zjzjtest type zjzjtest.
**=======end
SELECT ORGUNIT EMPLOYEE
INTO CORRESPONDING FIELDS OF TABLE t_docinfo
FROM /BI0/MEMPLOYEE FOR ALL ENTRIES IN RESULT_PACKAGE
WHERE EMPLOYEE = RESULT_PACKAGE-EMPLOYEE
"员工主数据表为 /BI0/MEMPLOYEE,其属性是与时间相关的,所以查询时需加上时间条件,
"读取业务数据产生时所对应的主数据. RESULT_PACKAGE-CALDAY 为业务发生的时间,
"dateto与datefrom为主数据的有效期
and datefrom <= RESULT_PACKAGE-CALDAY and dateto >=
RESULT_PACKAGE-CALDAY .
sort t_docinfo by EMPLOYEE ASCENDING.
LOOP AT RESULT_PACKAGE ASSIGNING <RESULT_FIELDS> .
READ TABLE t_docinfo WITH key EMPLOYEE = <RESULT_FIELDS>-EMPLOYEE
BINARY
SEARCH INTO wa_docinfo.
<RESULT_FIELDS>-ORGUNIT = wa_docinfo-ORGUNIT.
**=======调试使用
APPEND wa_docinfo-ORGUNIT to t_zjzjtest.
**=======end
ENDLOOP.
**=======调试使用
DELETE FROM zjzjtest.
MODIFY zjzjtest from TABLE t_zjzjtest.
**=======end
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "end_routine
*=== Segments ===
FIELD-SYMBOLS:
<RESULT_FIELDS> TYPE _ty_s_TG_1.
DATA:
MONITOR_REC TYPE rstmonitor.
*$*$ begin of routine - insert your code only below this line *-*
... "insert your code here
*-- fill table "MONITOR" with values of structure "MONITOR_REC"
*- to make monitor entries
... "to cancel the update process
* raise exception type CX_RSROUT_ABORT.
DATA:t_docinfo TYPE TABLE OF _ty_s_TG_1.
DATA:wa_docinfo TYPE _ty_s_TG_1.
**=======调试使用
Data: t_zjzjtest TYPE TABLE OF zjzjtest .
DATA wa_zjzjtest type zjzjtest.
**=======end
SELECT ORGUNIT EMPLOYEE
INTO CORRESPONDING FIELDS OF TABLE t_docinfo
FROM /BI0/MEMPLOYEE FOR ALL ENTRIES IN RESULT_PACKAGE
WHERE EMPLOYEE = RESULT_PACKAGE-EMPLOYEE
"员工主数据表为 /BI0/MEMPLOYEE,其属性是与时间相关的,所以查询时需加上时间条件,
"读取业务数据产生时所对应的主数据. RESULT_PACKAGE-CALDAY 为业务发生的时间,
"dateto与datefrom为主数据的有效期
and datefrom <= RESULT_PACKAGE-CALDAY and dateto >=
RESULT_PACKAGE-CALDAY .
sort t_docinfo by EMPLOYEE ASCENDING.
LOOP AT RESULT_PACKAGE ASSIGNING <RESULT_FIELDS> .
READ TABLE t_docinfo WITH key EMPLOYEE = <RESULT_FIELDS>-EMPLOYEE
BINARY
SEARCH INTO wa_docinfo.
<RESULT_FIELDS>-ORGUNIT = wa_docinfo-ORGUNIT.
**=======调试使用
APPEND wa_docinfo-ORGUNIT to t_zjzjtest.
**=======end
ENDLOOP.
**=======调试使用
DELETE FROM zjzjtest.
MODIFY zjzjtest from TABLE t_zjzjtest.
**=======end
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "end_routine
在第二层DSO中将OEMPLOYEE与 0ORGUNIT两个主数据一次全部读取出来: