Forum Discussion
Optimizing running total with a reset measure
- 4 years ago
Hi Anonymous
I happened to come across your post. I have had a play around and have attached a PBIX with some potential improvements.
The main things I looked at:
- Minimise nested measures (some overhead involved):
- Rewrote [Qty on Hand Total] using SUMX.
- Eliminated [Pos to Neg] and [No of Days (Internal)] from the final measure.
- Rather than using ALL ( 'Calendar'[Period Date] ), use a smaller date range covering global min/max Stock[Date].
- Rewrote the logic a bit to detect when the count should start. See AllRequiredDatesFlag variable.
- Rather than counting dates in a table containing a contiguous range of dates as in original _DatesToUse
variable, take the difference between date bounds & add 1.
A matrix with just Period Date & Working (IMPROVED) Measure now takes a bit under 2 seconds for me, or a bit over 3 seconds with Qty Projected as well.
The relevant updated measures are:
Qty On Hand Total = SUMX ( Stock, Stock[Qty On Hand] + Stock[Qty Supply] - Stock[Qty Demand] )Qty Projected = VAR MinStockDate = CALCULATE ( MIN ( Stock[Date] ), REMOVEFILTERS ( ) ) RETURN CALCULATE ( [Qty On Hand Total], DATESBETWEEN ( 'Calendar'[Period Date], MinStockDate, MAX ( 'Calendar'[Period Date] ) ) )Working (IMPROVED) Measure = VAR _RefDate = MAX ( Calendar[Period Date] ) VAR MinStockDate = CALCULATE ( MIN ( Stock[Date] ), REMOVEFILTERS ( ) ) VAR MaxStockDate = CALCULATE ( MAX ( Stock[Date] ), REMOVEFILTERS ( ) ) VAR AllRequiredDates = DATESBETWEEN ( Calendar[Period Date], MinStockDate, MaxStockDate ) VAR AllRequiredDatesFlag = ADDCOLUMNS ( AllRequiredDates, "@Pos", [Qty Projected] >= 0 ) VAR RelevantDatesFlag = FILTER ( AllRequiredDatesFlag, Calendar[Period Date] <= _RefDate ) VAR LastPositive = MAXX ( FILTER ( RelevantDatesFlag, [@Pos] ), Calendar[Period Date] ) VAR LastNegative = MAXX ( FILTER ( RelevantDatesFlag, NOT [@Pos] ), Calendar[Period Date] ) RETURN IF ( LastNegative = _RefDate, INT ( LastNegative - LastPositive ) )There's bound to be room for improvement, but hopefully this is of some use.
Regards,
Owen
- Minimise nested measures (some overhead involved):
I've no idea if this will be more efficient, but you could try something like
Running Total with reset =
var currentDate = SELECTEDVALUE('Calendar'[Date])
var summaryTable = ADDCOLUMNS(
SUMMARIZE( FILTER('Calendar', 'Calendar'[Date] < currentDate ), 'Calendar'[Date]), "@pos to neg", [Pos to Neg] )
var lastReset = SELECTCOLUMNS( TOPN(1, FILTER( summaryTable, [@pos to neg] = 1 ), [Date], ASC ),
"@last date", [Date] )
return COUNTROWS( DATESBETWEEN( 'Calendar'[Date], lastReset, currentDate ) )
Hello and thank you for taking interest in my question.
Sadly this does not work. It calculates a running total, but does not reset. The lastReset variables does not return anything.
- johnt754 years ago
Super User
could you share a small sample of data, ideally in a pbix file ?
- Anonymous4 years agoNot applicable
Hello
I have now created a sample pbix file with the data and a related calendar. The measure this post regards is called "Working (SLOW) Measure". I have visualized the matrix on page 1 as shown hereThis sample data only consists of one product (part 1713622). I have recreated the measures necessary for the calculation.
Does anyone know how I can possibly improve the performance of this measure?
When using the 'performance analyzer' in this sample file, it takes 20 seconds to refresh the matrix.
Some more information for those who wants to try:
No of days (internal) is = 1 if Qty Projected is < 0
'Pos to neg' = 1 if qty projected went from a positive number to a negative number
The 'Working (SLOW) Measure' is a running total of 'No of days (Internal)' that resets every time that 'Pos to Neg' = 1.
Thank you in advance for those willing to give it a shot!
Sample .pbix file uploaded to wetransfer.com: https://we.tl/t-mf6rT0A9Ou- johnt754 years ago
Super User
Try creating a summary table as a calculated table. That will obviously lead to increased data refresh time, but it will make populating report visuals pretty much instantaneous.
I created a table as
Summary Table = SUMMARIZECOLUMNS( 'Calendar'[Period Date], "@Qty Projected", [Qty Projected] )
Then added columns as
@Pos to Neg =
var currentDate = 'Summary Table'[Period Date]
var currentValue = 'Summary Table'[@Qty Projected]
var prevValue = LOOKUPVALUE( 'Summary Table'[@Qty Projected], 'Summary Table'[Period Date], currentDate -1 )
return IF( currentValue < 0 && prevValue > 0, 1 )
Running Total =
var currentDate = 'Summary Table'[Period Date]
var lastResetDate = SELECTCOLUMNS( TOPN( 1, FILTER( ALL('Summary Table'), 'Summary Table'[@Pos to Neg] =1 && 'Summary Table'[Period Date] < currentDate), 'Summary Table'[Period Date]),
"@last date", [Period Date])
return DATEDIFF( lastResetDate, currentDate, DAY )The problem with doing it all in measures is that it has to calculate the quantity twice for each date, once for today and once for yesterday, and each calculation is having to iterate over all the previous rows.