For any given date, I would like to get an average Sales of the most recent 3 days with non-blank sales. So I need to retrieve not only the last non-blank sales (which might be easy) but I also need to get the second last and third last sales. Generally, I need N'th last sales.
Sample data:
+------------+--------+--------+--------+--------+------------------+
| Date | Amount | N'th 1 | N'th 2 | N'th 3 | Expected Results |
+------------+--------+--------+--------+--------+------------------+
| 2021-02-01 | 1 | 1 | | | 1.00 |
| 2021-02-02 | 2 | 2 | 1 | | 1.50 |
| 2021-02-03 | 2 | 2 | 2 | 1 | 1.67 |
| 2021-02-04 | | 2 | 2 | 1 | 1.67 |
| 2021-02-05 | 3 | 3 | 2 | 2 | 2.33 |
| 2021-02-06 | | 3 | 2 | 2 | 2.33 |
| 2021-02-07 | | 3 | 2 | 2 | 2.33 |
| 2021-02-08 | 4 | 4 | 3 | 2 | 3.00 |
| 2021-02-09 | | 4 | 3 | 2 | 3.00 |
| 2021-02-10 | | 4 | 3 | 2 | 3.00 |
| 2021-02-11 | | 4 | 3 | 2 | 3.00 |
+------------+--------+--------+--------+--------+------------------+
The N'th 1 is the last "non-blank" sales. The N'th 2 is the "last but one". The expected result is the average of N1, N2, N3.
Link to sample data file with solutions suggested by accepted answer:
DAX Rolling Average NonBlanks.pbix
The proper way to filter for blanks in this case is to use the ISBLANK() function. Conversely, if you want to exclude only blanks, you wouldn't write <>BLANK() in your filter, but you'd use the NOT operator.
The COUNTAX function counts non-blank results when evaluating the result of an expression over a table. That is, it works just like the COUNTA function, but is used to iterate through the rows in a table and count rows where the specified expressions results in a non-blank result.
The “not equal to” operator <> returns TRUE when the two arguments do not have the same value. A comparison between BLANK and 0 or between BLANK and an empty string returns FALSE. Use the == operator to treat BLANK and 0 or empty string as different values.
If you want is to replace blank or null values with 0 without creating a new column, then use the Query Editor. Select Edit Query. In the query window, right click on the column header and select Replace Values...
LASTNONBLANK DAX Function (Time Intelligence) Context Transition. Returns the last value in the column for which the expression has a non blank value. LASTNONBLANK ( <ColumnName>, <Expression> ) The source values. The expression to be evaluated for each value.
The last non-blank value of <expression> corresponding to the sorted values of <column>. A reference to any column. A table with a single column.
When LASTNONBLANK is executed providing a column reference as the first argument, DAX implicitly rewrites the expression by retrieving the values using DISTINCT in a potential context transition. The previous code is internally rewritten as:
The DAX functions FIRSTNONBLANK, FIRSTNONBLANKVALUE, LASTNONBLANK, and LASTNONBLANKVALUE are iterators that could materialize data at the granularity of the column provided as a first argument.
Here's my take (it's a measure):
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = FILTER ( ADDCOLUMNS ( nonBlankTab, "Rank", RANKX ( nonBlankTab, [Date] ) ), [Rank] <= 3 )
return AVERAGEX(rankedTab, [Amount])
EDIT:
Just an explanation:
EDIT2:
I simplified the measure a bit - lastSalesDate is not necessary. Also, as per request in the comments, I left the first attempt as it was, and here is the modified version with TOPN instead of ADDCOLUMNS/RANKX/FILTER combo:
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])
EDIT3:
A more universal version of the measure that just removes filters from Date
column, which is actually all we need. No need to butcher all the other filters on the table:
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = CALCULATETABLE(FILTER(Data, NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate), REMOVEFILTERS(Data[Date]))
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With