https://zhuanlan.zhihu.com/p/96823622
開始半累加的計算之前,我們先看看什么是累加、半累加以及不可累加數據。
在含有大量行的數據表中,各種數據處理語言,包括DAX,為了性能考慮,不太可能總是檢索表的每一行,更常見的情形是,一次性檢索成千上萬行,處理如此多行數據的最有效操作就是將它們加到一起,也就是累加匯總。
可以累加的數據類型就是可累加數據,比如訂單表中的銷售額,就是這種類型,無論是按照客戶維度還是按照時間維度,都可以將每行的銷售額直接匯總,並且這種匯總的結果都是有效的、有意義的。
但有些數據是不可累加的,比如價格,雖然是數值,但無論如何累加都是沒有意義的,這就是不可累加數據,這類數據最常用的操作是計數或者取平均值。
還有些數據在某些情況下可以累加,但在特定情況下不可累加,比如銀行賬戶的資金余額,可以按照客戶維度進行匯總,但並不能按照時間維度進行每日資金余額的匯總操作,每日余額的匯總是沒有意義的,這樣的數據類型就稱為半累加數據。
在這三種類型中,最靈活最有用的當然是完全可累加數據,也是我們最常用的;而不可累加數據是最不靈活的,甚至可以當成是文本類型來看待。
居於其中的就是半累加數據,下面根據一個小例子來理解半累加度量,並看看如何在Power BI中進行它的計算。
假設每日庫存余額的數據如下:
新建一個基礎度量值:
庫存 = SUM('庫存表'[庫存余額])
半累加度量的可累加屬性
當計算每日的庫存合計余額時,結果是這樣的,
每日的庫存余額合計,實際上是在商品維度上匯總,此時體現的是它在商品維度的可累加屬性。
半累加度量的不可累加屬性
如果上下文是月份,把這個[庫存]度量值放進去,結果是這樣的,
這個結果實際上是每日的庫存余額簡單相加,明顯是無意義的數字,這時就體現了庫存余額在時間維度的不可累加屬性。
對於這個不可累加屬性,庫存更常見的計算是期末余額,實際上就是最后一天的余額,建個度量值如下:
期末庫存余額 = CALCULATE([庫存],LASTDATE('日期表'[日期]))
結果如下:
這樣1月和2月的結果就正確了,但有個問題是3月份竟然返回了空值?
這是因為LASTDATE返回的當前月份的最后一天,如果每日的庫存數據都很完整,這樣沒有問題,但實際情況是有些數據只顯示工作日的庫存,比如上面的例子,3月31日是周末,3月份庫存余額記錄的最后一天是3月29日。
因此需要計算最后一個有數據的日期的庫存余額,修改度量值如下,
期末庫存余額 優化= CALCULATE([庫存],FILTER(ALL('日期表'),'日期表'[日期]=MAX('庫存表'[日期])))
這樣就計算出了正確的結果,
還有個更簡單的寫法是利用LASTNONBLANK函數,找到最后一個有余額的日期,然后再計算該日期的庫存余額,
期末庫存余額 優化2= CALCULATE([庫存],LASTNONBLANK('日期表'[日期],[庫存]))
上面DAX的計算原理,就是先找出最后一天的日期,然后在這個日期,計算所有商品的累計庫存余額。
通過這個計算過程就能很清晰的理解半累加度量在時間維度上不可累加、在其他維度上可累加的屬性。
半累加度量的計算應注意細節,因為是數值型,在任一維度上累加都不會報錯,但某些結果很可能是無效的;不過當你清晰的認識到這個屬性以后,利用靈活的DAX,順暢的進行各種半累加度量的計算並不會成為問題。