DAX and the Measure Context
Measures are recipes evaluated in the current filter context
DAX is a filter-language engine, not a row calculator. CALCULATE is the verb that rewrites the filter context, and knowing the difference between row context and filter context explains most measure bugs.
What you will learn
- Explain row context vs filter context with a concrete example
- Write CALCULATE with a filter modifier and explain what it changes
- Convert a flat SUM into a grouped measure that total rows evaluate correctly
What is this?
A DAX measure is a formula evaluated for whatever the current context asks for — one year, one region, one customer or the grand total. The engine starts with the filter context (what is filtered) and a measure decides what to compute inside it. CALCULATE is the Swiss Army knife that changes that context: it removes, adds or overrides filters for a single calculation.
Why do you need it?
- Most 'wrong total' bugs in Power BI are really 'I summed a column instead of computing a measure'.
- Measures computed with CALCULATE stay correct no matter how the user slices the report.
- Row-level logic like running totals and dynamic groups is impossible without context control.
- Interviewers ask about context because it divides real modelers from drag-and-drop users.
Mental model
A waiter taking an order
A DAX measure
The waiter writes the order against the current table's context — table 4, party of three. Write the order once with a 'context' of table 4 and it stays correct when the party changes tables (context changes). CALCULATE is like sending a revised order note that overrides what was previously assumed.
How it works
- A card visual gives the measure an empty filter context — the whole table as one group.
- A slicer on region restricts the filter context to the selected regions.
- Row context exists only inside iterators like SUMX, FILTER and calculated columns, walking one row at a time.
- CALCULATE receives a base expression and a list of modifiers that rebuild the context.
- Context transition wraps row context into filter context when you navigate between tables.
One measure evaluated under three different filter contexts.
Examples
A share measure that survives slicers
Revenue This Year = CALCULATE( SUM(Orders[Amount]), 'Date'[Year] = 2026 ) Share of All Regions = DIVIDE( [Revenue This Year], CALCULATE( [Revenue This Year], ALL(Region[Region]) ) )The inner CALCULATE ignores the region filter from the visual, so the denominator is always the full-year revenue across all regions; the measure therefore reads 'what share of total did the selected region contribute'.
In production
- A 'share of total' measure divides a value by CALCULATE(value, ALL(region)) so the share is always relative to the full amount, even when filtered.
- A 'first order value' measure uses FILTER and MIN of order date, surviving any slicer because it is computed per customer inside an iterator.
- A finance team writes a 'last fiscal year total' measure with CALCULATE(SUM(sales), SAMEPERIODLASTYEAR('Date'[Date])) and it re-evaluates for whichever month the user selected.
Best practices
- Put every business rule in a measure, never in a calculated column that sums.
- Name measures by what they return ('Total Revenue (USD)') not by ".1" suffixes.
- Use ALL or ALLEXCEPT deliberately — broad ALL(Fact) with a locked date range is a common leak source.
- Write CALCULATE(SELECTEDVALUE(...)...) tolerant of blank selections instead of assuming a single filter.
Common mistakes
- Using SUM(column) when you need a ratio, then re-dividing a total that is already a sum.
- Forgetting that filter context flows from lookup tables to facts, not the other way around.
- Putting the whole formula in CALCULATE when only the filter part needs it.
- Comparing measures without accounting for the row on a report total — the context expands to all rows.
Common issues
Total of a % column is 150%Percentages were summed as a column instead of recomputed from sums via measures
Write a ratio measure that sums numerator and denominator inside the current context.
CALCULATE ignores my date slicerALL(Date) or ALL(Calendar) removed the date filter you expected to keep
Use ALLEXCEPT or apply the date filter inside the modifier instead of blanketing the table.
A calculated column is slow to refreshRow-context logic on millions of rows instead of a measure evaluated once per query
Move the logic into a measure; store materialized columns only when filters truly need them.
Debugging tips
- Isolate a measure on a card to see its true value without other visual interference.
- Build the expression inside a table visual with a few columns to walk row by row.
- Enable the DAX performance info in DAX Studio to see the query PAX generates.
- Comment out modifiers in CALCULATE one at a time to find which filter kills your value.
Interview checkpoint
Hands-on lab
- Load a sales table and a region dimension
- Write a base measure and a share measure
- Prove the share stays constant under a slicer
- Diagnose a broken total row
Tame the Filter Context
30 min · intermediate
Quick quiz
Which DAX function changes the filter context for one calculation?
A measure is stored on the row and summed by the total row automatically.