在這個小節中我們將計算度量值的 Year To Date 的值,也就是計算從年開始到當前時間成員為止的度量值的累加結果。
下面的這個查詢顯示了所有以周為單位的 Reseller Sales Amount -
那么如果要計算上圖中以周為單位的累加值,應該如何處理? 比如說現在是 Week 28 CY 2005,那么它的 YTD 累加值就是 Week 27 CY 2005 的度量值 + Week 28 CY 2005 度量值。
WITH MEMBER [Measures].[Reseller Sales YTD] AS SUM( YTD([Date].[Calendar Weeks].CurrentMember), [Measures].[Reseller Sales Amount] ) SELECT { [Measures].[Reseller Sales Amount], [Measures].[Reseller Sales YTD] } ON 0, {[Date].[Calendar Weeks].[Calendar Week].MEMBERS} ON 1 FROM [Adventure Works]
這樣就實現了這種累加值的計算,也叫 Running Total。
YTD() 函數返回是一個集合,是一個時間段的集合。它的起點是當前成員所在層次結構上的第一個時間成員,結束點就是這個當前成員自身。所以對於 Week 28 CY 2005 來說,它的 YTD 就是 Week 27 CY 2005 到 Week 28 CY 2005;對於 Week 35 CY 2005 來說,它的 YTD 還是從 Week 27 CY 2005 到它自身。
因此,如果看看 CY 2006 就會發現,YTD() 函數的確是以年作為一個時間參照開始的。並且要注意, CY 2005 的第一個 Week 成員就是 Week 27,但是在 CY 2006 的時候 Week 1 是在 Week 級別中的第一個成員。
還有另外一種比較簡單的方式計算累加,但是要注意這里的累加不再基於年,而是從當前層次結構上的第一個成員開始到當前成員的這段時間。
WITH MEMBER [Measures].[Reseller Sales YTD] AS Sum( (NULL: [Date].[Calendar Weeks].CurrentMember), [Measures].[Reseller Sales Amount] ) SELECT { [Measures].[Reseller Sales Amount], [Measures].[Reseller Sales YTD] }ON 0, {[Date].[Calendar Weeks].[Calendar Week].MEMBERS} ON 1 FROM [Adventure Works]
但是有要注意的地方,如果這里我們使用的是 Fiscal Week 而不是 Calendar 會出現什么問題?
WITH MEMBER [Measures].[Reseller Sales YTD] AS SUM( YTD([Date].[Fiscal Weeks].CurrentMember), [Measures].[Reseller Sales Amount] ) SELECT { [Measures].[Reseller Sales Amount], [Measures].[Reseller Sales YTD] } ON 0, {[Date].[Fiscal Weeks].[Fiscal Week].MEMBERS} ON 1 FROM [Adventure Works]
可以看到的結果是 YTD 的計算全部都不正確。
錯誤信息:By default, a year level was expected. No such level was found.
原因是為什么呢? [Date].[Calendar Weeks] 這個用戶自定義的層次結構有一個級別是 Calendar Year,它的類型是 Years。相對於 [Date].[Calendar Weeks] 的 Fiscal 層次結構是 [Date].[Fiscal Weeks],它有一個級別是 Fiscal Year,它的類型是 FiscalYear 而不是 Years。
YTD() 實際上是 PeriodsToDate() 函數的縮寫,但是它只能適用於含有 Year 這個類型級別的屬性層次結構。如果我們在開發過程中忘記這樣設計的話,那么我們就只可以使用 PeriodsToDate() 這種原型函數來實現 Year To Date 了。
WITH MEMBER [Measures].[Reseller Sales YTD] AS SUM( PeriodsToDate( [Date].[Fiscal Weeks].[Fiscal Year], [Date].[Fiscal Weeks].CurrentMember ), [Measures].[Reseller Sales Amount] ) SELECT { [Measures].[Reseller Sales Amount], [Measures].[Reseller Sales YTD] } ON 0, {[Date].[Fiscal Weeks].[Fiscal Week].MEMBERS} ON 1 FROM [Adventure Works]
查詢結果一樣是這樣的 Running Total 結果-
關於 PeriodsToDate() 函數的使用,我的這篇 MDX 讀書筆記中有詳細的解釋 - MDX Step by Step 讀書筆記(九) - Working with Time 處理時間
更多 BI WORK 博客系列看參看 - BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)