Study guide
5.2 The CALCULATE Function
Microsoft Power BI Data Analyst PL-300
Track your progress as you read
Finished sections get a check mark.
1 Introduction
About the PL-300 Exam The Power BI Ecosystem
2 Chapter 1: Get or Connect to Data
1.1 Data Source Types and Connections 1.2 Storage Modes: Import, DirectQuery, and Direct Lake 1.3 Data Source Settings and Parameters
3 Chapter 2: Profile and Clean the Data
2.1 Data Profiling in Power Query 2.2 Resolving Errors, Nulls, and Data Quality Issues 2.3 Data Types and Type Detection
4 Chapter 3: Transform and Load the Data
3.1 Column Transformations and Data Types 3.2 Grouping, Aggregating, Pivoting, and Unpivoting 3.3 Merge Queries, Append Queries, and Relationship Keys 3.4 Query Folding and Load Performance
5 Chapter 4: Design and Implement a Data Model
4.1 Star Schema Design 4.2 Relationships, Cardinality, and Cross-Filter Direction 4.3 Table and Column Properties 4.4 Calculated Columns and Calculated Tables
6 Chapter 5: Create Model Calculations with DAX
5.1 DAX Fundamentals and Measures 5.2 The CALCULATE Function 5.3 Time Intelligence Measures 5.4 Statistical Functions, Semi-Additive Measures, and Calculation Groups 5.5 Essential DAX Patterns and Functions Reference
7 Chapter 6: Optimize Model Performance
6.1 Performance Analyzer and DAX Query View 6.2 Model Size Reduction and Cardinality Management 6.3 DAX Optimization Patterns
8 Chapter 7: Create Reports
7.1 Visual Types and Selection 7.2 Visual Formatting and Conditional Formatting 7.3 Copilot in Power BI Reports 7.4 Report Page Configuration and Slicers
9 Chapter 8: Enhance Reports for Usability and Storytelling
8.1 Bookmarks, Navigation, and Drillthrough 8.2 Sorting, Selection Pane, Mobile Layout, and Accessibility 8.3 Export Settings and Automatic Page Refresh
10 Chapter 9: Identify Patterns and Trends
9.1 The Analyze Feature and AI Visuals 9.2 Using Copilot to Summarize the Semantic Model 9.3 Advanced Analytics Patterns
11 Chapter 10: Create and Manage Workspaces and Assets
10.1 Workspaces, Apps, and Content Distribution 10.2 Subscriptions, Alerts, and Semantic Model Refresh 10.3 Dashboards and Advanced Distribution
12 Chapter 11: Secure and Govern Power BI Items
11.1 Row-Level Security (RLS) 11.2 Sensitivity Labels, Item Access, and Governance 11.3 Deployment Pipelines and Content Lifecycle
5.2 The CALCULATE Function
Key Takeaways Explain This Topic AI
CALCULATE is the most important and most tested DAX function: it modifies filter context before evaluating an expression.
Syntax is CALCULATE(expression, filter1, filter2, ...); multiple filters combine with AND.
ALL()/REMOVEFILTERS() clear filters (for percent-of-total); ALLEXCEPT() clears all but the listed columns (for percent-of-parent).
FILTER() builds a row-by-row table filter and can reference measures, but is slower than direct column filters.
KEEPFILTERS() intersects a new filter with the existing context instead of overriding it; CALCULATE also performs context transition.
Last updated: June 2026
Quick Answer: CALCULATE modifies filter context before evaluating an expression, the only DAX function that does so directly. CALCULATE(SUM(Sales[Amount]), Products[Color] = "Red") sums Amount but only for Red products, regardless of the current color filter. ALL() removes filters; KEEPFILTERS() preserves them.
Why CALCULATE Is Critical
CALCULATE is the single most important DAX function because it is the only way to modify filter context inside a measure. Nearly every advanced pattern, time intelligence, percent-of-total, conditional aggregation, uses it.
How CALCULATE Works
It takes the current filter context (slicers, visuals, report filters).
It modifies that context with the supplied filters.
It evaluates the expression in the modified context. Red Revenue = CALCULATE(SUM(Sales[Amount]), Products[Color] = "Red")
- Revenue 2026 = CALCULATE(SUM(Sales[Amount]), 'Date'[Year] = 2026)
- Red Revenue 2026 = CALCULATE(SUM(Sales[Amount]), Products[Color] = "Red", 'Date'[Year] = 2026)
Multiple filters in one CALCULATE combine with AND . By default, a CALCULATE filter on a column overrides any existing filter on that same column.
- Filter Modifiers
- ALL() and REMOVEFILTERS()
ALL() removes filters from a table or columns; REMOVEFILTERS() is the same behavior with a clearer name when used as a CALCULATE modifier. Total Revenue All = CALCULATE(SUM(Sales[Amount]), ALL(Sales))
- Revenue All Colors = CALCULATE(SUM(Sales[Amount]), ALL(Products[Color]))
- Revenue No Date Filter = CALCULATE(SUM(Sales[Amount]), REMOVEFILTERS('Date'))
- ALLEXCEPT()
Removes filters from a table except the columns you list, the basis of percent-of-parent. Revenue by Category = CALCULATE(SUM(Sales[Amount]), ALLEXCEPT(Products, Products[Category]))
KEEPFILTERS()
By default CALCULATE overrides; KEEPFILTERS() instead intersects the new filter with the existing one. Blue Revenue = CALCULATE(SUM(Sales[Amount]), Products[Color] = "Blue")
// Overrides any color filter; always Blue.
Blue Revenue Kept = CALCULATE(SUM(Sales[Amount]), KEEPFILTERS(Products[Color] = "Blue"))
// Intersects: BLANK if the slicer is Red, Blue revenue if the slicer is Blue.
FILTER()
FILTER() builds a table by iterating rows; use it only when the condition references a measure , combines multiple columns , or needs a complex boolean . Premium Revenue = CALCULATE(SUM(Sales[Amount]), FILTER(Products, Products[Price] > 100))
Profitable Revenue = CALCULATE(SUM(Sales[Amount]), FILTER(Sales, Sales[Amount] > Sales[Cost]))
Performance: Direct column filters use the storage engine and are far faster than FILTER(). Reach for FILTER() only when necessary.
- Common CALCULATE Patterns
- Percentage of total (clear all filters for the denominator): % of Total Revenue =
- VAR CurrentRevenue = SUM(Sales[Amount])
- VAR TotalRevenue = CALCULATE(SUM(Sales[Amount]), ALL(Sales))
- RETURN DIVIDE(CurrentRevenue, TotalRevenue)
- Percentage of parent (keep the parent column with ALLEXCEPT): % of Category =
- VAR CurrentRevenue = SUM(Sales[Amount])
- VAR CategoryRevenue = CALCULATE(SUM(Sales[Amount]), ALLEXCEPT(Products, Products[Category]))
- RETURN DIVIDE(CurrentRevenue, CategoryRevenue)
- Conditional aggregation: Online Revenue = CALCULATE(SUM(Sales[Amount]), Sales[Channel] = "Online")
- Context Transition
When CALCULATE wraps an expression that has a row context, it converts that row context into filter context , called context transition . This is how a measure behaves correctly inside an iterator like SUMX: each row's context becomes a filter so the measure evaluates for that single row. Context transition is also why placing a measure name inside SUMX or a calculated column produces row-specific values automatically; the engine wraps measures in an implicit CALCULATE.
On the Exam
The PL-300 tests how CALCULATE modifies filter context, using ALL() for percent-of-total, direct filters vs. FILTER(), KEEPFILTERS() vs. default override, and combining CALCULATE with time intelligence.
CALCULATE Is the Hinge of Advanced DAX
Almost every interesting calculation, period comparisons, percentages, segment filters, what-if logic, is built by reshaping filter context, and CALCULATE is the only direct way to do it. Internally, CALCULATE evaluates its filter arguments first to produce new filter sets, applies them on top of (or in place of) the existing context, performs context transition if it is running inside a row context, and only then evaluates the expression. Knowing this order, filters first, context transition, then expression, explains many otherwise surprising results and is exactly the level of reasoning the exam's harder DAX items expect.
Override vs. Intersect: the KEEPFILTERS Distinction
The default behavior, a CALCULATE filter on a column replaces any existing filter on that column, is the source of countless mistakes. If a slicer already restricts Color to Red and your measure does CALCULATE(SUM(Sales[Amount]), Products[Color] = "Blue") , the slicer is ignored and you get Blue. Wrapping the predicate in KEEPFILTERS changes replacement into intersection , so the same measure returns BLANK when the slicer is Red (no overlap) and Blue's value when the slicer is Blue. Use plain CALCULATE filters when you genuinely want to ignore the user's selection, and KEEPFILTERS when you want to respect it.
Boolean Filters Are Sugar for FILTER + ALL
A simple predicate like Products[Color] = "Red" is shorthand the engine expands to FILTER(ALL(Products[Color]), Products[Color] = "Red") . That hidden ALL is why a boolean filter replaces rather than intersects, and it is why boolean filters are fast (they operate on a single column at the storage engine). When you instead pass FILTER(Products, ...) over the whole table, you lose that optimization and iterate every row in the formula engine. This is the precise reason direct column predicates outperform table FILTERs, a point the optimization section builds on.
CALCULATE Inside Iterators and Measures
A point worth internalizing: a measure referenced inside an iterator like SUMX , or referenced from another measure, is wrapped by the engine in an implicit CALCULATE , which is what triggers context transition. This is why SUMX(Customers, [Total Revenue]) returns each customer's revenue and then sums them, the row context for each customer becomes a filter context that the measure honors. It also explains a subtle gotcha: a variable defined before a CALCULATE captures the outer context, so referencing that variable inside the CALCULATE does not pick up the new filters.
When a calculation gives an unexpected total, the first questions to ask are "what context is this expression in" and "did a CALCULATE override or intersect the existing filters," which is exactly the reasoning the harder exam items reward.