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):
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
Hi OwenAuger and thank you for taking the time.
You certainly optimized it a lot, and it works as intended. Whether it's fast enough for production, I will have to analyze further. Before marking this as a solution I am exploring the table mentioned by johnt75. Although I believe this should be marked as the solution, even if the table functions better in production, since a measure was my original question.
- Mafesa_Sasol3 years agoFrequent Visitor
Hi Anonymous johnt75 OwenAuger I have been trying to follow the thread and looks like could be of assistance to my challenge. As can be seen from the attached snapshot. I am trying to develop a calculated column that does a running total for every specific employee using the date between standby column. That column is the Consecutive Employee Check. Please ignore the first value (11). However, I need it to reset after each value on the Days Between Standby Column that is greater than 1. For example, I need to reset 46, 22 and 8. However, the running total continues throughout which is not what I want. Your assistance would be highly appreciated. This is the sample for each unique ID and resets after each new ID but running total continues through for each and every unique ID and does not reset after each new value in the Days Between Standby greater than 1.
This is the DAX for this column:Consecutive Employee Check =VAR CurrentStandbyDays = LOOKUPVALUE(Standby[Standby Days], Standby[Index], Standby[Index])VAR ConsecStandbyDays =IF(LOOKUPVALUE(Standby[Personnel Number], Standby[Index], Standby[Index]) = LOOKUPVALUE(Standby[Personnel Number], Standby[Index], Standby[Index]+1)&& LOOKUPVALUE(Standby[Days Between Standby], Standby[Index], Standby[Index]) < 7 ,CALCULATE (SUM ( 'Standby'[Standby Days] ),FILTER ( ALLEXCEPT(Standby,'Standby'[Personnel Number], 'Standby'[Days Between Standby]), 'Standby'[Index] <= EARLIER ('Standby'[Index]))),CurrentStandbyDays)Return ConsecStandbyDays