Rotating Measures in DAX: When your data won't stay put
TL;DR
- Products that change category over time → “rotating measures” problem
- The client wants to see everything reclassified according to the latest period
- Pattern: capture the last period’s classification and apply it backwards
- Use REMOVEFILTERS + temp table with current classification
The mess
Let me paint you a scenario I’ve hit more than once: you have products (or customers, or whatever) that change categories over time. A product that was “Premium” in Q1 gets downgraded to “Standard” in Q2 because it didn’t sell as expected.
The user opens Power BI, selects Q1 and Q2 in the filter, and asks:
How much did we sell in Premium?
And here comes the awkward moment: do you sum what WAS Premium in Q1, or what IS Premium according to the current classification?
90% of the time, the client wants the latter. They want to see everything reclassified according to the latest period. But DAX, bless its heart, by default sums everything according to how it was classified at the time.
The solution: Rotating Measures
The pattern has a trick, but once you get it, it’s a piece of cake:
- Get the last period in the filter context
- Look up how products are classified IN THAT period
- Apply that classification backwards to ALL periods
Rotating Sales =
VAR LastPeriod =
MAXX(
VALUES(Calendar[Period]),
Calendar[Period]
)
VAR ClassifiedProducts =
CALCULATETABLE(
SUMMARIZE(
Products,
Products[ID],
Products[Category]
),
Products[Period] = LastPeriod
)
RETURN
CALCULATE(
[Sales],
REMOVEFILTERS(Products[Category]),
ClassifiedProducts
)
Why it works
- MAXX + VALUES: Gets the most recent period from what the user selected
- CALCULATETABLE + SUMMARIZE: Creates a temporary table with the classification snapshot from that period
- REMOVEFILTERS: Clears the original category filters (otherwise they’d clash)
- ClassifiedProducts: Reapplies the last period’s classification to the entire query
Basically you’re saying: “ignore how things were classified before, use ONLY the current classification.”
Bonus: showing the current category as text
If you also want a column that shows the current category (not summing, just showing text), the trick is SELECTEDVALUE:
Current Category =
VAR LastPeriod =
MAXX(
VALUES(Calendar[Period]),
Calendar[Period]
)
RETURN
CALCULATE(
SELECTEDVALUE(Products[Category]),
Products[Period] = LastPeriod
)
At totals it’ll return BLANK, which is correct. It doesn’t make sense to show a category when multiple products are mixed together.
Where you’ll need this
Any business where things change buckets:
- Retail with products that change season or section
- Services with clients that move up/down tiers
- Sales teams where reps change territory
- Inventory with products that get reclassified
If you have a dimension that isn’t static over time, sooner or later you’ll need this.
New to DAX? Start with my beginner’s guide before diving into these advanced patterns. If you want to understand time intelligence in more depth, my post on rolling 12 months covers another complex temporal pattern that often trips people up.
You might also like
Rolling 12 months in DAX: the two-calendar solution
How to calculate rolling 12 months in Power BI correctly. Step-by-step DAX tutorial.
What is DAX in Power BI: A Practical Guide for Beginners (with Examples)
Learn DAX from scratch: what it is, what it's for, difference from Power Query, the 5 essential functions, and common mistakes. With code examples.
Power BI Deactivated Your Relationship (And Didn't Tell You)
Complete guide to inactive relationships in Power BI: why they appear, how to detect them, USERELATIONSHIP, role-playing dimensions, and advanced patterns.