https://zhuanlan.zhihu.com/p/109964336
今年是閏年,有星友問我,在Power BI中,2月29日的上年同期是怎么計算的?
這是個好問題,正好梳理一下,PowerBI時間智能函數是如何處理不規則日期的對比數據的。
以一個模擬的訂單表數據為例,訂單日期涵蓋了2015年、2016年和2017年,其中2016年是閏年,添加一個相匹配的日期表與之建立關系,
先建立一個基礎度量值:
收入 = SUM('訂單表'[銷售額])
然后通過下面幾個示例,來看看幾個和2月29日相關的各種數據,是怎么計算的?以及時間智能函數處理閏年的計算邏輯。
2月29日-上年同期
建個上年同期的度量值:
收入 PY = CALCULATE( [收入], SAMEPERIODLASTYEAR('日期表'[日期]) )
把這個度量值放入到矩陣中看看結果:
從上面的數據可以看出,2016年2月29日和28日的上年同期數據都是48000,與2015年2月28日的數據是一樣的。
2016年2月28日的上年同期數據是2015年2月28日很正常,那么為什么2016年2月29日的上年同期數據也是2015年2月28日呢?
對於不規則的日期,根據特定的要求和邏輯,可以設計不同的對比方式。比如2015年是沒有2月29日的,那么2016年2月29日的上年同期可以設計為空值。而PowerBI的時間智能函數的計算邏輯,是2月29日的上年同期數據為上年2月28日的,換個角度可能更容易理解,就是2月最后一天的數據對比,無論是不是閏年。
並且觀察2017年2月28日的上年同期數據,與2016年2月28日的數據一樣,這很正常。只是在2017年,找不到這樣的日期:它的上年同期數據,可以與2016年2月29日對應。
2月29日-本年累計的上年同期
本年累計以及本年累計的上年同期度量值可以這樣寫:
收入 YTD = TOTALYTD([收入],'日期表'[日期])
收入 YTD PY = CALCULATE( [收入 YTD], SAMEPERIODLASTYEAR('日期表'[日期]))
計算結果如下:
本年累計的同期對比結果,與上面當日數據的同期對比邏輯是一樣的,依然是2016年2月29日的上年同期,是2015年2月28日的數據。
從上圖可以看到2017年2月28日上年同期的本年累計是4087000,但是如果看2017年2月份的上年同期本年累計,卻是4129000,
也就是說在本年累計的上年同期的計算中,2017年2月28日的數據和2017年2月份的數據是不一致的。
但在月份這個粒度上,2017年2月的上年同期,與2016年2月的數據完全一致,並沒有問題。
2月29日-本月累計的上月
需要建本月累計和上月累計的度量值,可以這樣寫:
收入 MTD = TOTALMTD([收入],'日期表'[日期])
收入 MTD PM = CALCULATE( [收入 MTD], DATEADD('日期表'[日期],-1,MONTH))
結果如下:
在月度環比上,因為每個月都有29號,29號本身的數據沒有問題,但在3月30號和3月31號的上月同期計算中,因為2月沒有對應的日期,所以都等於2月29日的數據。
關於月度環比,這個很正常,因為即使不是閏年,3月30日和3月31日的上月同期數據,也是都等於2月28日的數據。
在日期維度月度環比的計算上,不只是閏年有2月29日才存在這個問題,其實每年都存在,因為有的月份是31天,有的月份是30天,比如7月31號的上月同期數據就是6月30日的數據。
總結
通過上面幾個示例,對時間智能函數的計算邏輯總結如下:
- 日期粒度上的計算,如果沒有對應的日期,會自動等於上期最后一天的數據;
- 月份粒度上的計算,是否為閏年,沒有任何影響;
- 在本期累計的上期計算中,可能會出現,當月最后一天的累計數與當月的累計數不一致的情況。
以上就是時間智能函數的計算邏輯,其實沒有必要擔心2月29日的計算問題,就像不用擔心某個月是否有31號一樣。如果你的業務中,需要的計算邏輯不是時間智能函數的邏輯,應根據需求調整,按通用的DAX函數和規則來寫度量值,並不是一定要用時間智能函數。