Introducing VAR and RETURN
The VAR keyword lets a DAX author assign the result of an expression, whether a scalar value or an entire table, to a named variable that can then be referenced multiple times within the same formula, with the RETURN keyword marking the final expression that the whole measure evaluates to. A measure like VAR TotalSales = SUM(Sales[Amount]) VAR TotalCost = SUM(Sales[Cost]) RETURN DIVIDE(TotalSales - TotalCost, TotalSales) is far more readable than nesting the same SUM calls repeatedly inline.
Cricket analogy: VAR storing SUM(Sales[Amount]) once for reuse is like a scorer jotting down 'current run rate: 6.2' on a notepad once, then referencing that written number repeatedly instead of recalculating it from scratch for every subsequent question.
Performance Benefits of Variables
Because a variable is evaluated exactly once at the point it's defined and its result is then cached for every subsequent reference within that formula, using VAR to store a CALCULATE result that's needed twice, such as in both a numerator and denominator, avoids forcing the DAX engine to run that same CALCULATE expression's query plan twice. In complex measures with several nested CALCULATE calls referencing the same underlying aggregation, converting repeated sub-expressions into variables is one of the most reliable ways to meaningfully improve query performance in a large model.
Cricket analogy: Caching a variable's result once is like a broadcaster calculating a bowler's economy rate once per over and displaying that cached number on screen multiple times, rather than recomputing it from ball-by-ball data for every graphic.
Profit Margin % =
VAR TotalSales = SUM(Sales[Amount])
VAR TotalCost = SUM(Sales[Cost])
RETURN
DIVIDE(TotalSales - TotalCost, TotalSales)
Weighted Avg Price =
VAR Weighted = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
VAR TotalQty = SUM(Sales[Quantity])
RETURN
DIVIDE(Weighted, TotalQty)
Region Rank =
VAR RankingTable =
FILTER(ALL(Sales), Sales[Region] = SELECTEDVALUE(Sales[Region]))
RETURN
RANKX(RankingTable, [Total Sales])Variables and Row Context
A variable defined inside an iterator function like SUMX captures the row context that exists at the exact point it's assigned, which is particularly useful for locking in a value, such as the current row's date, before a nested CALCULATE later in the same expression triggers context transition and would otherwise overwrite that context. For example, VAR CurrentDate = Sales[Date] inside a SUMX iterator preserves the original row's date as a plain value that CALCULATE's context transition cannot subsequently alter.
Cricket analogy: A VAR locking in the current row's date before CALCULATE triggers context transition is like a scorer noting down the exact ball number before a DRS review potentially changes the on-field context, preserving the original reference point.
Combining Variables with Iterators for Complex Logic
Complex DAX patterns like ranking or weighted averages often store a table expression in a variable for reuse, such as VAR RankingTable = FILTER(ALL(Sales), Sales[Region] = SELECTEDVALUE(Sales[Region])) followed by RANKX(RankingTable, [Total Sales]), which avoids re-evaluating the same FILTER logic multiple times if it's referenced more than once. This pattern of combining VAR with iterator functions like SUMX or RANKX is the standard technique for building sophisticated measures such as a weighted average price, computed as VAR Weighted = SUMX(Sales, Sales[Quantity]*Sales[UnitPrice]) RETURN DIVIDE(Weighted, SUM(Sales[Quantity])).
Cricket analogy: Storing a filtered table in a variable for reuse in RANKX is like a selector shortlisting a specific pool of players once and then ranking within just that shortlist, rather than re-filtering the entire national player pool for every ranking question.
Once a VAR is assigned inside a formula, it cannot be reassigned — DAX variables behave like constants for the scope of that expression, unlike variables in imperative languages such as Python or C#.
- VAR assigns the result of an expression, scalar or table, to a named identifier for reuse.
- RETURN marks the final expression a measure evaluates to.
- A variable is evaluated exactly once and its result is cached for every later reference in the formula.
- Replacing repeated CALCULATE sub-expressions with variables is a reliable way to improve performance.
- A VAR defined inside an iterator captures the row context at that exact point of definition.
- Locking a row's value into a VAR protects it from being altered by a later context transition.
- Combining VAR with iterators like SUMX and RANKX is the standard pattern for weighted averages and rankings.
Practice what you learned
1. What can a DAX VAR store?
2. Why does using VAR to store a repeated CALCULATE result improve performance?
3. Can a DAX variable be reassigned later in the same formula?
4. Why would you define a VAR inside a SUMX iterator to capture a row's date?
5. What keyword marks the final expression a DAX measure evaluates to when using VAR?
Was this page helpful?
You May Also Like
Filter Context and CALCULATE
Filter context determines which rows a DAX measure sees, and CALCULATE is the only function that can directly reshape that context.
DAX Aggregation Functions
Aggregation functions like SUM, AVERAGE, COUNT, and their X-suffixed iterator counterparts are the workhorses for summarizing data in DAX measures.
Introduction to DAX
DAX (Data Analysis Expressions) is the formula language powering calculations in Power BI, Excel Power Pivot, and Analysis Services.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics