員工 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兩個主數據一次全部讀取出來: