ParallelPeriod 在日期維度中為 2 月 29 日返回 null
我有一個由物理日期表支持的日曆日期維度(最初是在 SQL Server 2000 上創建的,因此是日期時間而不是日期):
CREATE TABLE [dbo].[PostDate_Dimension]( [post_date] [datetime] NOT NULL PRIMARY KEY, [day_of_year] [int] NOT NULL, [day_of_month] [int] NOT NULL, [month_of_year] [int] NOT NULL, [post_year] AS (datepart(year,[post_date])), [post_month] AS (datepart(month,[post_date])), [post_day] AS (datepart(day,[post_date])) )
Post Date 維度有四個屬性(列出了成員鍵列,其中一些在 DSV 中計算):
- 日期(維度鍵)- post_date
- 月 - post_year, post_month
- 季度 - post_year,post_quarter =
DatePart(quarter, "post_date"))
- 年份 - post_year
顯然,這沒什麼太花哨的。我還有一些計算度量,它們使用 ParallelPeriod 來計算上一年的 YTD 數據,以便快速並排比較,而無需使用者選擇特定的日期片段。只需選擇目前年份,它就會找到其中包含銷售額的最新日期,然後與上一年的相同範圍進行比較。
在上一年找到合適的日期通常歸結為:
ParallelPeriod( [Post Date].[Post Date].[Year], 1, Tail( NonEmpty( Descendants( [Post Date].CurrentMember, , Leaves ), Measures.[Total Price] ), 1 ).Item(0) )
Tail 呼叫是它在目前選定的 Post Date 成員(通常是目前年份)下查找最新日期的地方。這很好用。但是,如果返回 2 月 29 日,這意味著特定維度成員組合的最後一次銷售發生在 2 月 29 日,那麼它將 2 月 29 日傳遞給 ParallelPeriod 函式,該函式隨後返回 null。然後上一年的 YTD 度量也返回 null。
所以,簡而言之:基於這個特定的模式,有沒有一種簡單的方法可以讓 ParallelPeriod 在 2 月 29 日的輸入中表現良好?如果它只是返回上一年的 2 月 28 日,那很好。
編輯:
我嘗試過的幾件事:
- 使用這個表達式來調整 Post Date 成員:
Iif(MONTH([Post Date].[Post Date].CurrentMember.Member_Caption) = 2 And DAY([Post Date].[Post Date].CurrentMember.Member_Caption) = 29, [Post Date].[Post Date].CurrentMember.PREVMEMBER, [Post Date].[Post Date].CurrentMember)
這行得通,但程式碼會很糟糕,因為我必須
[Post Date].[Post Date].CurrentMember
用Tail(NonEmpty(Descendants([Post Date].CurrentMember,, Leaves), Measures.[Total Price]), 1).Item(0))
.
- 使用 except 從結果中刪除所有 2 月 29 日的日期
NonEmpty(Descendants([Post Date].CurrentMember,, Leaves), Measures.[Total Price])
。我無法找出正確的語法(如果有的話)來從維度中獲取所有 2 月 29 日的集合。- 使用使用者定義函式創建一個 .NET 程序集,該函式將成員作為參數,如果是 2 月 29 日則返回前一個成員。似乎 Microsoft.AnalysisServices.AdomdServer 中的類非常有限,甚至沒有允許這個基本任務(甚至不檢索成員鍵作為日期值)。
另一種選擇是使用聯合來獲取目前和前一個成員的並行時間段。然後從中提取第一項,它將始終是目前成員(除了 2 月 29 日的情況,它應該回退到前一個成員)。
也就是說,與前一個成員並行週期有效合併,如下所示:
union ( PARALLELPERIOD( [Date].[Fiscal Detail].[Fiscal Year],1, [Date].[Fiscal Detail].currentmember) *(will be null if Feb 29)* , PARALLELPERIOD( [Date].[Fiscal Detail].[Fiscal Year],1, [Date].[Fiscal Detail].currentmember.lag(1)) *(will be the prior year Feb 28 when above is Feb 29 )* ).item(0) *(get the first member out of the union set)*