Logical
Checks a condition, and returns one value when TRUE, otherwise it returns a second value
IF(<logical_test>, <value_if_true>, <value_if_false>)
Comprehensive Guide to the DAX IF Function
Overview
The IF function is one of the most fundamental logical functions in DAX, enabling conditional logic in your data models. It evaluates a condition and returns different values based on whether the condition is TRUE or FALSE. This function is essential for creating dynamic calculations, categorizations, and business logic in Power BI, Excel Power Pivot, and Analysis Services.
Applies to:Β Calculated columns, Calculated tables, Measures, Visual calculations
Syntax
IF ( <logical_test>, <value_if_true> [, <value_if_false>] )
Parameters
Parameter | Required | Description | Examples |
logical_test | Yes | Any value or expression that evaluates to TRUE or FALSE | [Sales] > 1000,Β [Status] = "Active",Β [Date] >= TODAY() |
value_if_true | Yes | The value returned when logical_test is TRUE | "High",Β [Sales] * 1.1,Β 1,Β BLANK() |
value_if_false | No | The value returned when logical_test is FALSE. If omitted, returns BLANK | "Low",Β [Sales],Β 0,Β "N/A" |
Return Value
Returns one of three possibilities:
value_if_trueΒ (when condition is TRUE)value_if_falseΒ (when condition is FALSE)BLANK()Β (when condition is FALSE and value_if_false is omitted)
Key Concepts and Behavior
1.Β Data Type Handling
The IF function attempts to return a consistent data type, but behavior varies:
Same Numeric Types
// Both branches are numbers - returns consistent numeric type
Discount = IF( [Sales] > 1000, 0.10, 0.05 ) // Returns: 0.10 or 0.05
Different Numeric Types
// Whole number and decimal - implicitly converts to decimal
Result = IF( [Sales] > 1000, 1.0, 0 ) // Returns: 1.0 or 0.0 (both decimal)
Mixed Data Types (Variant)
// Text and number - returns variant data type
Result = IF( [Sales] > 1000, TRUE(), 0 ) // Returns: TRUE or 0 (variant)
Result = IF( [Status] = "Active", "Yes", 1 ) // Returns: "Yes" or 1 (variant)
Best Practice:Β Keep both branches the same data type to avoid unexpected behavior and maintain clarity.
2.Β BLANK Handling
WhenΒ value_if_falseΒ is omitted, BLANK is automatically returned:
// Explicit approach
Status = IF( [Sales] > 0, "Has Sales", BLANK() )
// Implicit approach (same result)
Status = IF( [Sales] > 0, "Has Sales" )
Important:Β BLANK is different from an empty string (""), zero (0), or FALSE:
- BLANK in numeric context = 0
- BLANK in text context = "" (empty string)
- BLANK in boolean context = FALSE
3.Β Evaluation Behavior
Standard IF evaluates BOTH branches before selecting which to return:
// Both CALCULATE expressions are evaluated, even though only one is returned
Result = IF(
[Total Sales] > 0,
CALCULATE( [Profit], Sales[Region] = "North" ), // Evaluated
CALCULATE( [Profit], Sales[Region] = "South" ) // Also evaluated
)
Alternative:Β For performance-critical scenarios where you want to evaluate only the selected branch, useΒ IF.EAGER(available in newer DAX versions).
Practical Examples by Complexity
Basic Examples
Example 1: Simple Classification
// Classify products as Low or BLANK
Price Category =
IF(
'Product'[List Price] < 500,
"Low"
)
// Returns: "Low" if price < 500, otherwise BLANK
Example 2: Binary Classification
// Classify products as Low or High
Price Category =
IF(
'Product'[List Price] < 500,
"Low",
"High"
)
// Returns: "Low" if price < 500, otherwise "High"
Example 3: Active Status Check
// Check if customer is active
Is Active =
IF(
'Customer'[Last Purchase Date] >= TODAY() - 365,
"Active",
"Inactive"
)
Nested IF Examples
Example 4: Three-Tier Classification
// Classify products into Low, Medium, or High
Price Group =
IF(
'Product'[List Price] < 500,
"Low",
IF(
'Product'[List Price] < 1500,
"Medium",
"High"
)
)
Logic Flow:
- If price < 500 β "Low"
- Else if price < 1500 β "Medium"
- Else β "High"
Example 5: Multi-Level Sales Performance
// Categorize sales performance
Performance Rating =
IF(
[Total Sales] >= 1000000,
"Excellent",
IF(
[Total Sales] >= 500000,
"Good",
IF(
[Total Sales] >= 100000,
"Average",
"Below Target"
)
)
)
Example 6: Complex Business Logic
// Calculate commission based on sales and tenure
Commission Rate =
VAR SalesAmount = [Total Sales]
VAR YearsEmployed = [Employee Tenure Years]
RETURN
IF(
YearsEmployed >= 10,
IF( SalesAmount >= 500000, 0.15, 0.12 ),
IF(
YearsEmployed >= 5,
IF( SalesAmount >= 500000, 0.12, 0.10 ),
IF( SalesAmount >= 500000, 0.10, 0.08 )
)
)
Professional Use Cases
Use Case 1: Conditional Calculations
// Apply discount only when sales exceed threshold
Discounted Price =
VAR BasePrice = [Unit Price]
VAR Quantity = [Order Quantity]
RETURN
IF(
Quantity >= 100,
BasePrice * 0.90, // 10% discount
BasePrice
)
Use Case 2: Error Handling
// Safely calculate percentage with division by zero protection
Profit Margin =
VAR Revenue = [Total Revenue]
VAR Cost = [Total Cost]
RETURN
IF(
Revenue > 0,
DIVIDE( Revenue - Cost, Revenue ),
BLANK()
)
Note:Β DIVIDE function has built-in divide-by-zero handling, but IF provides more control over error scenarios.
Use Case 3: Date-Based Logic
// Identify current, future, or past orders
Order Status =
VAR OrderDate = 'Orders'[Order Date]
VAR TodayDate = TODAY()
RETURN
IF(
OrderDate > TodayDate,
"Future Order",
IF(
OrderDate = TodayDate,
"Today's Order",
"Past Order"
)
)
Use Case 4: Conditional Aggregation
// Count only high-value customers
High Value Customer Count =
CALCULATE(
COUNTROWS( 'Customer' ),
IF(
[Customer Lifetime Value] >= 10000,
TRUE(),
FALSE()
)
)
// Alternative using FILTER (often more efficient)
High Value Customer Count =
CALCULATE(
COUNTROWS( 'Customer' ),
'Customer'[Lifetime Value] >= 10000
)
Use Case 5: Dynamic Formatting Text
// Create formatted status message
Order Summary =
VAR OrderValue = [Order Total]
VAR OrderCount = [Order Quantity]
RETURN
IF(
OrderValue > 0,
"Order: " & FORMAT( OrderCount, "0" ) & " items - " &
FORMAT( OrderValue, "$#,0.00" ),
"No orders"
)
Use Case 6: Budget Variance Analysis
// Determine if over or under budget
Budget Status =
VAR Actual = [Actual Spending]
VAR Budget = [Budget Amount]
VAR Variance = Actual - Budget
RETURN
IF(
Variance = 0,
"On Budget",
IF(
Variance > 0,
"Over Budget by " & FORMAT( ABS( Variance ), "$#,0" ),
"Under Budget by " & FORMAT( ABS( Variance ), "$#,0" )
)
)
Use Case 7: Conditional Time Intelligence
// Calculate year-over-year growth, handling first year
YoY Growth % =
VAR CurrentYear = [Sales Amount]
VAR PreviousYear = CALCULATE( [Sales Amount], SAMEPERIODLASTYEAR( 'Date'[Date] ) )
RETURN
IF(
NOT ISBLANK( PreviousYear ),
DIVIDE( CurrentYear - PreviousYear, PreviousYear ),
BLANK()
)
When to Use SWITCH Instead of Nested IF
For multiple conditions with simple equality tests,Β SWITCHΒ is more readable and maintainable:
Nested IF (Less Readable)
Region Name =
IF(
[Region Code] = "N",
"North",
IF(
[Region Code] = "S",
"South",
IF(
[Region Code] = "E",
"East",
IF(
[Region Code] = "W",
"West",
"Unknown"
)
)
)
)
SWITCH (More Readable) β
Region Name =
SWITCH(
[Region Code],
"N", "North",
"S", "South",
"E", "East",
"W", "West",
"Unknown" // Default value
)
Use SWITCH when:
- Testing a single expression against multiple values
- You have 3+ possible outcomes
- All tests are simple equality comparisons
Use IF when:
- You need complex logical tests (>, <, AND, OR)
- Different conditions test different expressions
- You need only 2-3 outcomes with complex logic
Combining IF with Other Functions
With AND/OR for Multiple Conditions
// Customer is qualified if both conditions are true
Is Qualified =
IF(
AND(
[Total Purchases] >= 5000,
[Account Age Days] >= 180
),
"Qualified",
"Not Qualified"
)
// Apply discount if ANY condition is true
Gets Discount =
IF(
OR(
[Is VIP Customer] = TRUE(),
[Order Amount] > 1000,
[Referral Code] <> BLANK()
),
"Yes",
"No"
)
With ISBLANK for Null Checking
// Provide default value when data is missing
Display Name =
IF(
ISBLANK( 'Customer'[Nickname] ),
'Customer'[Full Name],
'Customer'[Nickname]
)
// Handle missing dates
Days Since Last Order =
IF(
NOT ISBLANK( 'Customer'[Last Order Date] ),
INT( TODAY() - 'Customer'[Last Order Date] ),
BLANK()
)
With CALCULATE for Conditional Aggregation
// Sum only for specific conditions
Qualified Revenue =
CALCULATE(
SUM( Sales[Revenue] ),
IF(
Sales[Status] = "Approved" && Sales[Amount] >= 1000,
TRUE(),
FALSE()
)
)
// Better approach using direct filter
Qualified Revenue =
CALCULATE(
SUM( Sales[Revenue] ),
Sales[Status] = "Approved",
Sales[Amount] >= 1000
)
With SELECTEDVALUE for Single Selection
// Display metric based on user selection
Selected Metric =
VAR Selection = SELECTEDVALUE( 'Metric Selector'[Metric Name] )
RETURN
IF(
Selection = "Revenue",
[Total Revenue],
IF(
Selection = "Profit",
[Total Profit],
[Total Sales] // Default
)
)
// Better with SWITCH
Selected Metric =
SWITCH(
SELECTEDVALUE( 'Metric Selector'[Metric Name] ),
"Revenue", [Total Revenue],
"Profit", [Total Profit],
[Total Sales] // Default
)
Common Patterns and Best Practices
Pattern 1: Flag Columns
// Create binary flag for filtering
Is High Value =
IF( [Customer Lifetime Value] >= 10000, 1, 0 )
// Use in measures
High Value Sales =
CALCULATE(
[Total Sales],
'Customer'[Is High Value] = 1
)
Pattern 2: Conditional Text with Variables
// More readable with variables
Status Message =
VAR Outstanding = [Outstanding Balance]
VAR DaysPastDue = [Days Past Due]
RETURN
IF(
Outstanding = 0,
"Paid in Full",
IF(
DaysPastDue > 90,
"Severely Overdue",
IF(
DaysPastDue > 30,
"Overdue",
"Current"
)
)
)
Pattern 3: Fallback Values
// Provide sensible defaults
Display Price =
IF(
NOT ISBLANK( 'Product'[Sale Price] ),
'Product'[Sale Price],
'Product'[List Price]
)
Pattern 4: Time Period Comparison
// Compare current period to previous
Period Comparison =
VAR CurrentPeriod = [Sales Amount]
VAR PreviousPeriod = [Sales Amount Previous Period]
RETURN
IF(
ISBLANK( PreviousPeriod ),
"No Comparison Data",
IF(
CurrentPeriod > PreviousPeriod,
"Increased",
IF(
CurrentPeriod < PreviousPeriod,
"Decreased",
"Unchanged"
)
)
)
Performance Considerations
1.Β Avoid Unnecessary IF in Calculated Columns
βΒ Less Efficient:
// IF statement evaluated for every row
Revenue Category =
IF(
Sales[Revenue] >= 10000,
"High",
IF(
Sales[Revenue] >= 5000,
"Medium",
"Low"
)
)
β Β More EfficientΒ (when possible, pre-calculate in source):
-- In SQL/Power Query
CASE
WHEN Revenue >= 10000 THEN 'High'
WHEN Revenue >= 5000 THEN 'Medium'
ELSE 'Low'
END AS RevenueCategory
2.Β Use Filter Context Instead of IF When Possible
βΒ Less Efficient:
Active Customer Sales =
SUMX(
Sales,
IF( RELATED( Customer[Status] ) = "Active", Sales[Amount], 0 )
)
β Β More Efficient:
Active Customer Sales =
CALCULATE(
SUM( Sales[Amount] ),
Customer[Status] = "Active"
)
3.Β Minimize Nested IF Depth
- Keep nesting to 3 levels maximum for readability
- Consider SWITCH for deeper logic
- Break complex logic into multiple calculated columns/variables
Common Pitfalls and Solutions
Pitfall 1: Testing for BLANK Incorrectly
βΒ Wrong:
Has Value = IF( [Value] = BLANK(), "No", "Yes" )
β Β Correct:
Has Value = IF( ISBLANK( [Value] ), "No", "Yes" )
Pitfall 2: Comparing Text Without Considering Case
// DAX is case-insensitive for comparisons
Status Check =
IF( [Status] = "active", "Active", "Inactive" )
// This matches "active", "Active", "ACTIVE", etc.
// To be case-sensitive, use EXACT
Status Check =
IF( EXACT( [Status], "active" ), "Active", "Inactive" )
Pitfall 3: Forgetting Data Type Consistency
βΒ Problematic:
Result = IF( [Sales] > 0, "Has Sales", 0 ) // Returns text or number
β Β Better:
Result = IF( [Sales] > 0, "Has Sales", "No Sales" ) // Consistent text
// OR
Result = IF( [Sales] > 0, 1, 0 ) // Consistent number
Pitfall 4: Not Handling Missing Related Data
βΒ Can Cause Errors:
Customer Segment =
IF(
RELATED( Customer[Tier] ) = "Gold",
"Premium",
"Standard"
)
// Fails if relationship doesn't return a value
β Β Robust:
Customer Segment =
VAR CustomerTier = RELATED( Customer[Tier] )
RETURN
IF(
NOT ISBLANK( CustomerTier ) && CustomerTier = "Gold",
"Premium",
"Standard"
)
Quick Reference: IF Decision Tree
Is the condition a simple equality test of one expression against multiple values?
ββ YES β Use SWITCH
ββ NO β Continue
β
Are there only 2 outcomes?
ββ YES β Use simple IF
ββ NO β Continue
β
Are there 3-5 outcomes with different logical tests?
ββ YES β Use nested IF
ββ NO (>5 outcomes) β Consider SWITCH with complex expressions or table-based lookup
Comparison: IF vs. Alternatives
Scenario | IF | SWITCH | Alternative |
2 outcomes | β
Best | β Overkill | - |
3-4 outcomes (equality) | β οΈ Acceptable | β
Best | - |
5+ outcomes (equality) | β Unreadable | β
Best | Lookup table |
Complex logical tests | β
Best | β Not suitable | Multiple measures |
Combining multiple conditions | β
Best (with AND/OR) | β Limited | FILTER function |
Conditional aggregation | β οΈ Works | β Not applicable | β
CALCULATE with filter |
Integration with FORMAT Function
Combining IF with FORMAT for professional output:
// Conditional formatting based on value
Sales Display =
VAR SalesValue = [Total Sales]
RETURN
IF(
SalesValue >= 1000000,
FORMAT( SalesValue, "$#,0,,.0M" ),
IF(
SalesValue >= 1000,
FORMAT( SalesValue, "$#,0,.0K" ),
FORMAT( SalesValue, "$#,0" )
)
)
// Status with colored indicators (for use in Power BI)
Status Indicator =
VAR Variance = [Actual] - [Budget]
RETURN
IF(
Variance > 0,
"π΄ Over: " & FORMAT( ABS( Variance ), "$#,0" ),
IF(
Variance < 0,
"π’ Under: " & FORMAT( ABS( Variance ), "$#,0" ),
"π‘ On Target"
)
)
// Date-based conditional display
Period Label =
VAR CurrentDate = MAX( 'Date'[Date] )
RETURN
IF(
YEAR( CurrentDate ) = YEAR( TODAY() ),
FORMAT( CurrentDate, "mmm yyyy" ) & " (Current Year)",
FORMAT( CurrentDate, "mmm yyyy" )
)
Summary Table
Aspect | Key Takeaway |
Purpose | Conditional logic returning different values based on TRUE/FALSE evaluation |
Basic Usage | IF( condition, true_value, false_value ) |
Omitted FALSE | Returns BLANK() when third parameter omitted |
Data Types | Attempts to return consistent type; converts numerics implicitly |
Nesting Limit | Technically unlimited, but keep to 3 levels for readability |
Performance | Both branches are evaluated; consider IF.EAGER for optimization |
Best Alternative | SWITCH for multiple equality tests on same expression |
Common With | AND, OR, ISBLANK, CALCULATE, RELATED, FORMAT |
Primary Use Cases | Classifications, conditional calculations, error handling, dynamic text |
Final Recommendations for Professional Use
β Β DO:
- Keep conditions simple and readable
- Use variables to make complex logic clearer
- Maintain consistent data types in return values
- Handle BLANK values explicitly with ISBLANK()
- Consider SWITCH for 3+ simple equality tests
- Document complex nested logic with comments
βΒ DON'T:
- Nest more than 3-4 levels deep
- Mix data types in return values unnecessarily
- Use IF when CALCULATE with filters is more appropriate
- Forget to handle NULL/BLANK scenarios
- Ignore performance implications in calculated columns
The IF function is a fundamental building block in DAX. Master it alongside SWITCH, AND, OR, and filter functions to create sophisticated business logic in your Power BI reports.