Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.
My goal is to get a waterfall graph, showing items' change in cost across time.
I have a table akin to this:
Shipment Data
Item | Ship Date | Extended Cost | Quantity | Unit Cost |
Item A | 1/1/2020 | 500 | 1 | 500 |
Item A | 1/1/2020 | 1100 | 2 | 550 |
Item A | 1/2/2020 | 1200 | 2 | 600 |
Item A | 1/15/2020 | 510 | 1 | 510 |
Item B | 1/10/2020 | 2000 | 2 | 1000 |
Item B | 1/12/2020 | 1200 | 1 | 1200 |
The issue I'm running into is the PreviousDateWithCost component is finding the last date with any cost, rather than taking into account the item-level filtering at the visualization level.
Cost Delta =
VAR PreviousDateWithCost =
CALCULATE (
MAX( [Ship Date] ),
FILTER ( ALL ( 'Shipment Data' ),[Extended Cost] > 0 && [Quantity] > 0 && [Ship Date] < MAX ( [Ship Date] ) && [Item] = [Item])
)
VAR PreviousCost =
CALCULATE (
DIVIDE( SUM ( [Extended Cost] ) , SUM ( [Quantity] ) ),
FILTER ( ALL ( 'Shipment Data' ), [Ship Date] = PreviousDateWithCost && [Item] = [Item])
)
RETURN
[Unit Cost] / PreviousCost
Solved! Go to Solution.
Hi @Nathan_O ,
If you want to get each item's max date to calculate, try to modify the formula like this:
Cost Delta =
VAR _previousdate =
CALCULATE (
MAX ( [Ship Date] ),
FILTER (
ALLEXCEPT ( 'Shipment Data', 'Shipment Data'[Item] ),
[Extend Cost] > 0
&& [Quantity] > 0
)
)
VAR _previouscost =
CALCULATE (
DIVIDE ( SUM ( [Extend Cost] ), SUM ( [Quantity] ), BLANK () ),
FILTER (
ALLEXCEPT ( 'Shipment Data', 'Shipment Data'[Item] ),
[Ship Date] = _previousdate
)
)
RETURN
[Unit Cost] / _previouscost
Best Regards,
Yingjie Li
If this post helps then please consider Accept it as the solution to help the other members find it more quickly.
Hi @Nathan_O ,
If you want to get each item's max date to calculate, try to modify the formula like this:
Cost Delta =
VAR _previousdate =
CALCULATE (
MAX ( [Ship Date] ),
FILTER (
ALLEXCEPT ( 'Shipment Data', 'Shipment Data'[Item] ),
[Extend Cost] > 0
&& [Quantity] > 0
)
)
VAR _previouscost =
CALCULATE (
DIVIDE ( SUM ( [Extend Cost] ), SUM ( [Quantity] ), BLANK () ),
FILTER (
ALLEXCEPT ( 'Shipment Data', 'Shipment Data'[Item] ),
[Ship Date] = _previousdate
)
)
RETURN
[Unit Cost] / _previouscost
Best Regards,
Yingjie Li
If this post helps then please consider Accept it as the solution to help the other members find it more quickly.
Hi @v-yingjl and @edhans, thanks for the help!
I tried implementing v-yingjl's code, and that got me most of the way there, but I ran into a snag; the measure is pulling the most recent ship date, instead of the prior date before the measure's context.
I've duplicated the _previousdate into _currentdate and added [Ship Date] to the ALLEXCEPT formula to return the row's ship date. Then in _previousdate, added a filter for [Ship Date] < _currentdate and that solved the issue.
Lastly, the earliest dates in the table were returning _previousdate = 0 and _previouscost = 0. So I added an intermediary variable to replace _previousdate = 0 with _currentdate.
Cost Delta =
VAR _currentdate =
CALCULATE (
MAX( [Ship Date] ),
FILTER (
ALLEXCEPT( 'Shipment Data' , 'Shipment Data'[Item] , 'Shipment Data'[Ship Date] ),
[Extended Cost] > 0
&& [Quantity] > 0
)
)
VAR _previousdate =
CALCULATE (
MAX( [Ship Date] ),
FILTER (
ALLEXCEPT( 'Shipment Data' , 'Shipment Data'[Item] ),
[Extended Cost] > 0
&& [Quantity] > 0
&& [Ship Date] < _currentdate
)
)
VAR _effectivepreviousdate =
IF(_previousdate = 0,_currentdate,_previousdate)
VAR _previouscost =
CALCULATE (
DIVIDE( SUM ( [Extended Cost] ) , SUM ( [Quantity] ) , 0 ),
FILTER (
ALLEXCEPT( 'Shipment Data' , 'Shipment Data'[Item] ),
[Ship Date] = _effectivepreviousdate
)
)
RETURN
[Unit Cost] / _previouscost
Item | Ship Date | Extended Cost | Quantity | Unit Cost | Goal Date | v-yingjl's _previousdate | _currentdate | _previousdate | _effectivepreviousdate |
Item A | 1/1/2020 | 500 | 1 | 500 | 1/1/2020 | 1/15/2020 | 1/1/2020 | 0 | 1/1/2020 |
Item A | 1/1/2020 | 1100 | 2 | 550 | 1/1/2020 | 1/15/2020 | 1/1/2020 | 0 | 1/1/2020 |
Item A | 1/2/2020 | 1200 | 2 | 600 | 1/1/2020 | 1/15/2020 | 1/2/2020 | 1/1/2020 | 1/1/2020 |
Item A | 1/15/2020 | 510 | 1 | 510 | 1/2/2020 | 1/15/2020 | 1/15/2020 | 1/2/2020 | 1/2/2020 |
Item B | 1/10/2020 | 2000 | 2 | 1000 | 1/10/2020 | 1/12/2020 | 1/10/2020 | 0 | 1/10/2020 |
Item B | 1/12/2020 | 1200 | 1 | 1200 | 1/10/2020 | 1/12/2020 | 1/12/2020 | 1/10/2020 | 1/10/2020 |
There is probably a more elegant way of doing this, but the code above accomplishes the goal! Thank you guys so much for the help! Any cleanup tips would be greatly appreciated.
This measure will do that.
Max Date =
VAR LastDateWithAnyCost =
MAXX(
FILTER(
ALL( 'Table' ),
'Table'[Unit Cost] <> 0
),
'Table'[Ship Date]
)
RETURN
LastDateWithAnyCost
It returns the below data.
Your measure above is calling a lot of other measures, and one is [item] = [item] which doesn't make much since since 1 = 1, and all of those measures are getting some context transition because the whole thing is wrapped in CALCULATE and measures get an implicit CALCULATE() when reused, so the amount of filtering going on there is a lot, and may be difficult to track down. I'd componentize the whole thing and not call a lot of other measures if possible, and ditch CALCULATE() if possible.
DAX is for Analysis. Power Query is for Data Modeling
Proud to be a Super User!
MCSA: BI ReportingCovering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City
Check out the April 2024 Power BI update to learn about new features.
User | Count |
---|---|
106 | |
94 | |
77 | |
65 | |
53 |
User | Count |
---|---|
145 | |
105 | |
104 | |
90 | |
63 |