DAX measures do not return one fixed value. They are evaluated inside a filter context created by the visual, slicers, page and report filters, relationships, and the DAX expression itself. For PL-300 analysts, understanding that context explains why the same measure changes across rows, totals, and visuals. DP-600 builds on the same behavior in larger semantic-model engineering scenarios.
CALCULATE is the central DAX function for changing that filter context. It evaluates an expression after adding, replacing, removing, or otherwise modifying filters. The syntax is simple; the difficulty is predicting which filters already exist, how relationships propagate them, and whether the new filter replaces or intersects with the current context.
Filter context comes from the query around the measure
A table or matrix row creates filters for the category values displayed on that row. A slicer adds another filter, while page and report filters add more. Relationships propagate filters from dimension tables to related fact tables. The measure evaluates after those filters combine, which is why one measure definition can return a different result for each cell.
Read a visual by asking which columns are currently filtered. Add cross-highlighting and drill state to that mental model: another visual can create additional filters, and drill-down can change the level of a hierarchy being evaluated. The same measure can therefore produce a different number without any change to its DAX definition or underlying fact rows. If a matrix shows Year on rows and Product Category on columns, each cell evaluates the measure for one year-category intersection. Totals are not obtained by simply adding visible cells unless the measure logic produces that result; the total is evaluated again under the broader total filter context.
Row context is different from filter context
Row context means an expression is being evaluated for a current row, as in a calculated column or an iterator such as SUMX. Row context by itself does not automatically filter related fact data in the same way a visual filter does. This distinction is one of the reasons calculated columns and measures can return very different results even when the formulas look similar.
Model measures are naturally evaluated in filter context. Calculated columns are computed and stored at data-refresh time, while measures are evaluated at query time under the current context. Choosing a calculated column merely to avoid learning filter context can increase model size and produce a value that does not respond to report interactions. When a measure is invoked inside an iterator, DAX can perform context transition automatically for the measure. When a non-measure expression needs the current row converted into filters, CALCULATE without explicit filter arguments can trigger that context transition.
CALCULATE adds filters when none exist
A simple CALCULATE expression can add a new filter to the evaluation. For example, a measure can calculate revenue only for blue products by applying a Product Color filter. Filters on unrelated columns remain in effect, so the result still responds to current year, geography, channel, and other context unless the expression explicitly changes those filters too.
This is why CALCULATE is compositional rather than global. Nested CALCULATE expressions can create layers of context modification, which is powerful but hard to read. Prefer small measures and explicit variables so each context change has a clear business purpose and can be tested independently. It creates a modified context for one expression. After the expression returns, the surrounding query continues with its own context. Thinking in terms of temporary evaluation context is more accurate than imagining that CALCULATE permanently changes the model.
CALCULATE replaces filters on the same columns by default
When CALCULATE applies a filter to a column that is already filtered, the new filter normally replaces the existing filter on that column. A visual filtered to Red products can therefore return Blue revenue if the measure explicitly sets Product Color to Blue. This replacement behavior is often exactly what percentage-of-total or fixed-segment measures need.
The rest of the current filter context stays in place. Boolean filter arguments have restrictions, and more complex conditions may require a table expression such as FILTER. Use the simplest form that expresses the rule because filter-table construction can add computational cost and obscure which columns are actually being changed. If the visual is also filtered to 2026 and Europe, replacing Product Color does not automatically remove Year or Region. Debugging DAX becomes much easier when each filter argument is analyzed by column rather than treating context as one opaque state.
KEEPFILTERS intersects instead of replacing
KEEPFILTERS changes the normal replacement behavior so a CALCULATE filter intersects with an existing filter on the same column. If the visual currently allows Red and Blue and the measure uses KEEPFILTERS for Blue, the intersection is Blue rather than replacing the user’s filter with a broader set.
Use KEEPFILTERS when the measure should narrow the caller’s choice rather than override it. It is particularly useful in reusable measures that define a subset, such as premium products or active customers, while still allowing a report consumer to choose an even smaller subset through slicers. The intersection behavior should be part of the measure documentation. It is especially useful in reusable measures that need to impose a constraint while respecting slicer or report intent. Test cases with overlapping and non-overlapping filters make the behavior easier to understand than memorizing the function in isolation.
REMOVEFILTERS and ALL create denominator contexts
Percentage measures often need a denominator evaluated with one filter removed. REMOVEFILTERS can clear a column or table filter inside CALCULATE, allowing a measure to compare the current selection with a broader total. ALL and related functions can also remove filters and, depending on use, return tables for other calculations.
Remove only the filters the business definition requires. REMOVEFILTERS on a dimension is usually easier to reason about than broadly clearing a fact table because the dimension is the natural source of the user filter. Test denominator measures at detail and total levels so the percentage still expresses the intended comparison at every visual grain. A percent-of-category measure may need to remove Product but keep Year and Region. Clearing the entire fact table can accidentally ignore user selections that should remain meaningful and can make totals difficult for report consumers to explain.
Relationships participate in filter context
A filter on a dimension propagates through active model relationships according to cardinality and cross-filter direction. CALCULATE can use USERELATIONSHIP to activate an inactive relationship for one expression, which is useful for role-playing scenarios such as Order Date versus Ship Date. CROSSFILTER can change relationship direction or disable a relationship during evaluation.
These functions are powerful but should not compensate for a confusing model. An inactive relationship activated with USERELATIONSHIP is understandable for an alternate date, but repeated CROSSFILTER manipulation across many measures can signal that model relationships or dimensional design need review. DAX should express business calculation, not continuously repair topology. If many measures need custom relationship manipulation, review the star schema and relationship design. A clear semantic model reduces the amount of DAX required to produce predictable filtering.
Use variables and simple base measures to debug context
Complex measures are easier to reason about when built from small base measures such as total sales, total quantity, or customer count. Variables can capture intermediate values and prevent repeated expressions. Then CALCULATE expressions can focus on context changes rather than mixing filtering, arithmetic, and business rules in one long formula.
Test the measure in a simple matrix with the relevant dimension columns before placing it in a complex dashboard. Include zero, blank, single-selection, multi-selection, and total scenarios. A formula that looks correct for one filtered row may produce an unexpected grand total because totals are evaluated in their own broader filter context. Add one slicer at a time and compare detail rows with totals. DAX Query View and Performance Analyzer can expose the query generated by a visual when the result or performance is unclear.
Context mastery produces reusable measures
The goal is not to memorize every DAX filter function. Use DAX Query View to experiment with small queries and inspect intermediate behavior outside a complex report page. This shortens the feedback loop when learning how filters and relationships affect a measure. It is to recognize the context entering a measure, understand which columns CALCULATE changes, and predict how relationships propagate the result. Once that model is clear, calculations such as share of total, year-over-year comparison, alternate date analysis, and fixed business segments become variations of the same principle.
Keep measures named and documented around business meaning rather than technical tricks. Organize related measures in display folders or a dedicated measures table, reuse base measures rather than duplicating SUM expressions, and add descriptions for calculations that intentionally ignore or replace user filters. A semantic model becomes much easier to maintain when context behavior is explicit. A semantic model is easier to maintain when another analyst can understand why a measure changes context and which user filters it intentionally respects or overrides.
When a measure becomes difficult to reason about, decompose it with variables and inspect intermediate results under known filter selections. Ask which filters existed before CALCULATE, which arguments replaced or added filters, and whether context transition introduced filters from the current row. This method is more reliable than memorizing function combinations because it follows the evaluation context the engine actually receives, especially inside iterators or nested measures.