Other
DAX Variables (VAR): Comprehensive Study Guide
Overview
VAR is a DAX keyword that allows you to define variables within your DAX expressions. Variables store intermediate calculations or values that can be referenced multiple times throughout your measure or calculated column, improving code readability, maintainability, and often performance.
Syntax Structure
VAR VariableName = Expression
VAR AnotherVariable = Expression
RETURN
FinalExpression
Key Components:
- VAR: Keyword that declares a variable
- VariableName: The name you assign to the variable (follows standard DAX naming conventions)
- Expression: The DAX expression whose result will be stored in the variable
- RETURN: Required keyword that specifies the final expression to be returned by the measure
- FinalExpression: The calculation that uses the variables and produces the final result
Why Use Variables?
1. Code Readability & Maintainability
Without Variables:
Profit Margin % =
DIVIDE(
SUM(Sales[SalesAmount]) - SUM(Sales[TotalProductCost]),
SUM(Sales[SalesAmount])
) * 100
With Variables:
Profit Margin % =
VAR TotalSales = SUM(Sales[SalesAmount])
VAR TotalCosts = SUM(Sales[TotalProductCost])
VAR GrossProfit = TotalSales - TotalCosts
VAR MarginPercentage = DIVIDE(GrossProfit, TotalSales, 0) * 100
RETURN
MarginPercentage
The second version is self-documenting - anyone reading the code immediately understands what each component represents.
2. Performance Optimization
When you repeat the same expression multiple times, DAX may calculate it multiple times. Variables ensure the expression is evaluated once and the result is reused.
Without Variables (Inefficient):
Sales Variance =
DIVIDE(
SUM(Sales[SalesAmount]) - CALCULATE(SUM(Sales[SalesAmount]), PREVIOUSMONTH(Calendar[Date])),
CALCULATE(SUM(Sales[SalesAmount]), PREVIOUSMONTH(Calendar[Date]))
)
The CALCULATE with PREVIOUSMONTH is evaluated twice.
With Variables (Efficient):
Sales Variance =
VAR CurrentSales = SUM(Sales[SalesAmount])
VAR PreviousMonthSales = CALCULATE(SUM(Sales[SalesAmount]), PREVIOUSMONTH(Calendar[Date]))
VAR Variance = DIVIDE(CurrentSales - PreviousMonthSales, PreviousMonthSales, 0)
RETURN
Variance
Each expression is evaluated only once.
3. Avoiding Repetition (DRY Principle)
Variables eliminate the need to write the same complex expression multiple times, reducing errors and simplifying future updates.
4. Easier Debugging
When building complex measures, you can test each variable independently in DAX Studio or by creating separate measures, making it easier to identify where issues occur.
How Variables Work: Evaluation Context
Critical Concept: Variables Capture Context at Definition
When a variable is defined, it immediately evaluates in the current filter context and row context. The variable stores the result, not the expression itself.
Example Demonstrating Context Capture:
Sales Analysis =
VAR AllCustomerSales = SUM(Sales[SalesAmount]) -- Evaluated in current filter context
VAR TotalCompanySales = CALCULATE(SUM(Sales[SalesAmount]), ALL(Customer))
VAR CustomerContribution = DIVIDE(AllCustomerSales, TotalCompanySales, 0)
RETURN
CustomerContribution
When used in a report:
- If the visual is filtered to "Customer = Contoso Ltd",
AllCustomerSalesis calculated for Contoso Ltd only TotalCompanySalesremoves the customer filter and calculates for all customers- The variable stores these specific values, not the formulas
Variables Are Constants
Once evaluated, a variable's value does not change during the execution of the measure, even if you apply additional filters later in the RETURN statement.
Demo Measure =
VAR BaseSales = SUM(Sales[SalesAmount]) -- Evaluated at current context
RETURN
CALCULATE(
BaseSales, -- This is a fixed value, not recalculated
Product[Category] = "Bikes"
)
In this example, BaseSales is NOT recalculated for just Bikes. It remains the value calculated when the variable was defined.
Practical Business Scenarios
Scenario 1: Year-over-Year Growth Analysis
Business Context: The sales manager needs to see current year sales, previous year sales, and the percentage growth for the Contoso stores.
YoY Sales Growth % =
VAR CurrentYearSales = SUM(Sales[SalesAmount])
VAR PreviousYearSales =
CALCULATE(
SUM(Sales[SalesAmount]),
SAMEPERIODLASTYEAR(Calendar[Date])
)
VAR SalesGrowth = CurrentYearSales - PreviousYearSales
VAR GrowthPercentage =
DIVIDE(
SalesGrowth,
PreviousYearSales,
BLANK() -- Return BLANK if no previous year data
)
RETURN
GrowthPercentage
Benefits:
- Clear naming shows business logic
- Easy to modify if calculation needs to change
- Each component can be tested separately
Scenario 2: Customer Segmentation Score
Business Context: Categorize customers based on multiple criteria (total purchases, frequency, recency).
Scenario 3: Inventory Turnover Ratio
Business Context: Calculate how quickly inventory is sold and replaced.
Best Practices for Using Variables
1. Use Descriptive Names
❌ Poor Naming:
VAR x = SUM(Sales[SalesAmount])
VAR y = SUM(Sales[TotalProductCost])
VAR z = x - y
✅ Good Naming:
VAR TotalRevenue = SUM(Sales[SalesAmount])
VAR TotalCosts = SUM(Sales[TotalProductCost])
VAR GrossProfit = TotalRevenue - TotalCosts
2. Order Variables Logically
Arrange variables in the order they're calculated or used, making the logic flow clear.
Sales Performance =
VAR CurrentSales = SUM(Sales[SalesAmount])
VAR Target = [Sales Target]
VAR Variance = CurrentSales - Target
VAR VariancePercentage = DIVIDE(Variance, Target, 0)
RETURN
VariancePercentage
3. Break Complex Calculations into Steps
Instead of one giant expression, use multiple variables to show the calculation journey.
Weighted Average Price =
VAR TotalRevenue = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
VAR TotalQuantity = SUM(Sales[Quantity])
VAR WeightedAvg = DIVIDE(TotalRevenue, TotalQuantity, BLANK())
RETURN
WeightedAvg
4. Always Include RETURN
Every measure using VAR must end with RETURN. The RETURN statement specifies what the measure actually displays.
My Measure =
VAR Result = 100
RETURN
Result -- This is what appears in your visual
5. Use Variables for Complex Filter Contexts
When you need to calculate values in different filter contexts, variables make the intent clear.
Market Share % =
VAR ProductSales = SUM(Sales[SalesAmount])
VAR CategorySales =
CALCULATE(
SUM(Sales[SalesAmount]),
ALLSELECTED(Product[ProductName])
)
VAR MarketShare = DIVIDE(ProductSales, CategorySales, 0)
RETURN
MarketShare
Common Pitfalls & How to Avoid Them
Pitfall 1: Trying to Modify Variable Values
❌ This Won't Work:
Invalid Measure =
VAR Counter = 0
VAR Counter = Counter + 1 -- ERROR: Variable already defined
RETURN
Counter
Why: Variables in DAX are immutable (cannot be changed after definition). You cannot reassign values to existing variables.
✅ Solution: Use different variable names for each step:
Valid Measure =
VAR InitialValue = 0
VAR AdjustedValue = InitialValue + 1
RETURN
AdjustedValue
Pitfall 2: Misunderstanding Context Capture
Problem Scenario:
Incorrect Sales Filter =
VAR BaseSales = SUM(Sales[SalesAmount]) -- Captures current context
RETURN
CALCULATE(
BaseSales, -- This is a scalar value, not recalculated
Product[Category] = "Bikes"
)
Why It's Wrong: BaseSales is evaluated when the variable is defined. The CALCULATE doesn't recalculate it for Bikes; it just applies the filter to the already-calculated value (which doesn't make sense).
✅ Correct Approach:
Correct Sales Filter =
VAR BikeSales =
CALCULATE(
SUM(Sales[SalesAmount]),
Product[Category] = "Bikes"
)
RETURN
BikeSales
Pitfall 3: Using Variables in Calculated Columns vs. Measures
Variables work in both, but context is different:
Calculated Column (Row Context):
Column With VAR =
VAR UnitPrice = Product[UnitPrice]
VAR UnitCost = Product[UnitCost]
VAR Margin = UnitPrice - UnitCost
RETURN
Margin
Each variable evaluates for the current row.
Measure (Filter Context):
Measure With VAR =
VAR TotalSales = SUM(Sales[SalesAmount])
VAR TotalCosts = SUM(Sales[TotalProductCost])
VAR Profit = TotalSales - TotalCosts
RETURN
Profit
Variables evaluate based on the current filter context from slicers, filters, rows, columns.
Performance Considerations
When Variables Help Performance
- Avoiding Repeated Calculations:
- If the same aggregation appears 3+ times, using a variable typically improves performance
- Storing Complex Filter Context:
- Variables can store expensive CALCULATE operations that would otherwise run multiple times
When Variables Don't Help
- Simple Direct References:
- Over-Optimization:
- Don't use variables for every single expression; only when it improves clarity or avoids actual repetition
-- This variable adds no value
Unnecessary =
VAR Sales = [Total Sales]
RETURN
Sales
Performance Testing
Always test complex measures using DAX Studio to compare execution times with and without variables for your specific data model.
Comparison: With vs. Without Variables
Example: Customer Lifetime Value
Without Variables (Hard to Read):
CLV =
(SUMX(
FILTER(Sales, Sales[CustomerKey] = EARLIER(Sales[CustomerKey])),
Sales[SalesAmount]
) /
CALCULATE(
DISTINCTCOUNT(Sales[OrderDate]),
FILTER(Sales, Sales[CustomerKey] = EARLIER(Sales[CustomerKey]))
)) *
DATEDIFF(
MIN(Sales[OrderDate]),
MAX(Sales[OrderDate]),
MONTH
)
With Variables (Clear Business Logic):
Advanced Variable Techniques
Technique 1: Variables with Table Results
Variables can store entire tables, not just scalar values.
Top 3 Products by Sales =
VAR TopProducts =
TOPN(
3,
VALUES(Product[ProductName]),
[Total Sales],
DESC
)
VAR TopProductSales =
CALCULATE(
[Total Sales],
TopProducts
)
RETURN
TopProductSales
Technique 2: Nesting Variables with Iterators
Weighted Margin =
VAR WeightedProfitTable =
ADDCOLUMNS(
Sales,
"RowProfit",
VAR RowRevenue = Sales[SalesAmount]
VAR RowCost = Sales[TotalProductCost]
RETURN RowRevenue - RowCost
)
VAR TotalWeightedProfit = SUMX(WeightedProfitTable, [RowProfit])
RETURN
TotalWeightedProfit
Technique 3: Error Handling with Variables
Safe Division Measure =
VAR Numerator = SUM(Sales[SalesAmount])
VAR Denominator = SUM(Sales[Quantity])
VAR Result =
IF(
Denominator = 0,
BLANK(),
DIVIDE(Numerator, Denominator)
)
RETURN
Result
PL-300 Exam Focus Areas
What You Need to Know:
- Syntax Requirements:
- VAR keyword must be followed by variable name and expression
- RETURN keyword is mandatory
- Multiple variables can be defined sequentially
- Context Behavior:
- Variables evaluate immediately when defined
- Variables capture the current filter and row context
- Variable values don't change during measure execution
- Use Cases:
- Improving measure readability
- Avoiding repeated calculations for performance
- Breaking complex logic into manageable steps
- Storing intermediate table results
- Best Practices:
- Descriptive naming conventions
- Logical ordering of variables
- Appropriate use for both calculated columns and measures
Common Exam Question Types:
- Code Analysis: Given a measure with variables, what will it return in specific filter contexts?
- Error Identification: Spot incorrect variable usage or syntax errors
- Optimization: Choose the most efficient version of a measure (with/without variables)
- Code Completion: Fill in missing VAR statements to complete a measure
Practice Exercise
Scenario: You work for Contoso analyzing product profitability. Create a measure that shows:
- Total Revenue for each product
- Total Cost for each product
- Gross Profit
- Profit Margin %
- Flag products with margin below 20% as "Low Margin"
Your Task: Write the measure using variables following best practices.
<details> <summary><strong>Solution</strong></summary>
Alternative - Return just the margin percentage:
Product Profit Margin % =
VAR Revenue = SUM(Sales[SalesAmount])
VAR Cost = SUM(Sales[TotalProductCost])
VAR Profit = Revenue - Cost
VAR Margin = DIVIDE(Profit, Revenue, BLANK())
RETURN
Margin
</details>
Quick Reference Summary
Aspect | Key Points |
Purpose | Store intermediate calculations, improve readability, enhance performance |
Syntax | VAR Name = Expression followed by RETURN FinalExpression |
Evaluation | Variables evaluate immediately when defined in current context |
Mutability | Variables are immutable (cannot be reassigned) |
Scope | Variable values are constant throughout measure execution |
Performance | Prevents redundant calculation of repeated expressions |
Use Cases | Complex calculations, time intelligence, filtering, aggregations |
Best Practice | Use descriptive names, logical ordering, clear step-by-step logic |
Key Takeaways
- VAR improves DAX quality through better readability and maintainability
- Variables evaluate once and store results, not expressions
- Context matters - variables capture filter and row context at definition
- RETURN is mandatory - it specifies the measure's final output
- Strategic use - apply variables when they add clarity or avoid repetition, not everywhere
- Performance benefit - most significant when avoiding repeated complex calculations
For Your Notion Database:
- Category: DAX Functions - Utility
- Exam Coverage: PL-300 - Model Development
- Difficulty: Intermediate
- Related Topics: Filter Context, Row Context, CALCULATE, Iterator Functions