Forum Discussion
Rolling Average Averagex, Time Intelligence with Date Table is incorrectly ignoring zero sales day
Thank you for the clarification; although, that particular point is not mentioned in ANY documentation I can find on Averagex or the time intelligence functions. Also that rationalization doesn't make sense.
When averaged over all sales for a company for every product category, this might be accecptible. However, this behavior quickly breaks down when you start considering product segments or departments. Many product or server categories are infrequently sold. Think mortgages, roofing jobs, cars, airplanes, trains, dirt, accounting services, etc. It is a false equivalence to assume that because a product was not sold on a day than it must be a weekend or a holiday.
For instance If Boeing were to use Averagex track the daily averages sales for 747s, the calculated result would be WAY off. They may only sale 1 a quarter.
In my particular industry we are heavy tracking equipment utilization. A heavy equipment hauler might genrate $3000 a day, but only work 3 days in a week. However, there are expenses such as debt servicing, insurance, and maintenance that accure daily. As such we need to track the weekly and monthly revenue averages that a machine is generating in to make sure it is turning a profit.
I'm new to PowerBi, buy i've been a professional programmer for decades, and it boggles my mind that this unwritten behavior is acceptable. There is no telling how many incorrect dashboards have been built around the world based upon the misconception that AVERAGEX(DATESINPERIOD(Dates[Date],LASTDATE(Dates[Date]),-7,DAY),[Total Sales]) does NOT in fact return an average of total sales over the unbroken, uninterrupted date range that I pass into the function! It is exacly like Microsoft saying "4/2 = 2 but there are exceptions where sometimes it's 4 or 1, but those exceptions are not spelled out or detailed anywhere. Good luck in finding them."
For those searching why your time intelligence functions are not working properly, here is a working DAX implementation of a true 2 week moving average.
2 Week Moving Average =
CALCULATE(
[Total Sales],
DATESINPERIOD(Dates[Date],LASTDATE(Dates[Date]),-14, DAY))
/
CALCULATE(
DISTINCTCOUNT(Dates[Date]),
DATESINPERIOD(Dates[Date],LASTDATE(Dates[Date]),-14, DAY))
If you want to filter out working days from nonworking days, the proper procedure is to create a class label in your date table to which you can group, filter and calculate across. So for instance you can cateorgize your dates into "WorkDays" and "OffDays". In which case the above calculation becomes:
2 Week Moving Average =
CALCULATE(
[Total Sales],
DATESINPERIOD(Dates[Date],LASTDATE(Dates[Date]),-14, DAY),
FILTER(ALLSELECTED(Dates),Dates[Day Type] = "WorkDay"))
/
CALCULATE(
DISTINCTCOUNT(Dates[Date]),
DATESINPERIOD(Dates[Date],LASTDATE(Dates[Date]),-14, DAY),
FILTER(ALLSELECTED(Dates),Dates[Day Type] = "WorkDay"))
Averagex and the other time intelligence functions could be easily fixed to correctly accomodate nonworking days, by accepting an optional filter parameter. Until then however I'm afraid that recreating these base methods is the only alternative.
Thank you!