Field-tested rules for writing maintainable, performant DAX measures.
| Type | Pattern | Example |
|---|---|---|
| Base measure | Total {Noun} | Total Revenue, Total Orders |
| Rate/Percentage | {Noun} % or {Noun} Rate | Conversion Rate, Margin % |
| Comparison | {Metric} {Period} | Revenue Prior Year, Revenue YTD |
| Growth | {Metric} {Period} Growth | Revenue YoY Growth |
| Conditional | {Metric} ({Condition}) | Revenue (New Customers) |
| Helper/Hidden | Prefix with _ | _Filtered Revenue Base |
Organize measures into folders in the model:
Revenue/
├── Total Revenue
├── Revenue YTD
├── Revenue MTD
├── Revenue Prior Year
└── Revenue YoY Growth
Customers/
├── Unique Customers
├── New Customers
├── Returning Customers
└── Customer Retention Rate
Targets/
├── Budget Amount
├── Variance to Budget
├── Budget Attainment %
└── Budget Status
-- BAD: Calculates [Total Revenue] twice
Growth % =
DIVIDE(
[Total Revenue] - [Revenue SPLY],
[Revenue SPLY]
)
-- GOOD: Calculate once, use twice
Growth % =
VAR CurrentRevenue = [Total Revenue]
VAR PriorRevenue = [Revenue SPLY]
RETURN
DIVIDE(CurrentRevenue - PriorRevenue, PriorRevenue, BLANK())-- BAD: Will error on divide-by-zero
Margin = ([Revenue] - [Cost]) / [Revenue]
-- GOOD: Returns BLANK() when denominator is zero
Margin = DIVIDE([Revenue] - [Cost], [Revenue], BLANK())-- BAD: SUMX iterates every row even if SUM would work
Total Revenue = SUMX('Sales', 'Sales'[Amount])
-- GOOD: SUM is optimized for single-column aggregation
Total Revenue = SUM('Sales'[Amount])
-- USE SUMX ONLY WHEN: you need row-level calculation
Total Revenue =
SUMX('Sales', 'Sales'[Quantity] * 'Sales'[Unit Price] * (1 - 'Sales'[Discount]))-- GOOD: Optimized for distinct counting
Unique Customers = DISTINCTCOUNT('Orders'[Customer ID])
-- AVOID: Creates intermediate table
Unique Customers = COUNTROWS(VALUES('Orders'[Customer ID]))
-- Only use VALUES() when you need the actual table for further operations-- Know what ALL, ALLEXCEPT, ALLSELECTED do:
-- ALL() = Removes ALL filters on the table/column
-- ALLSELECTED() = Removes filters from the visual, keeps slicer filters
-- ALLEXCEPT() = Removes all filters EXCEPT specified columns
-- REMOVEFILTERS() = Same as ALL() but reads better in context
-- Use ALLSELECTED for "percentage of visible total"
Share of Visible Total =
DIVIDE([Total Revenue], CALCULATE([Total Revenue], ALLSELECTED('Products')))-- FAILS: A references B, B references A
Measure A = [Measure B] + 1
Measure B = [Measure A] - 1
-- FIX: Extract shared logic into a base measure
_Base = SUM('Table'[Amount])
Measure A = [_Base] + 1
Measure B = [_Base] - 1-- UNNECESSARY: CALCULATE with no filter modification
Revenue = CALCULATE(SUM('Sales'[Amount]))
-- CLEANER: Direct aggregation
Revenue = SUM('Sales'[Amount])-- PROBLEM: Subtraction with BLANK produces BLANK
Change = [Revenue This Year] - [Revenue Last Year]
-- If Last Year is BLANK (new product), Change is BLANK too
-- FIX: Handle BLANK explicitly
Change =
VAR Prior = IF(ISBLANK([Revenue Last Year]), 0, [Revenue Last Year])
RETURN
[Revenue This Year] - Prior-- If you need to filter one table by values from an unrelated table:
Revenue for Budget Products =
CALCULATE(
[Total Revenue],
TREATAS(VALUES('Budget'[Product ID]), 'Sales'[Product ID])
)Every Power BI model with time intelligence NEEDS a proper date table:
1. Contiguous dates — No gaps from earliest to latest date in your data
2. Mark as Date Table — Right-click → Mark as Date Table → select date column
3. Minimum columns: Date, Year, Quarter, Month, Month Name, Day of Week
4. Fiscal calendar columns if you use fiscal periods
5. Relationship: One-to-many from Calendar[Date] to Fact[Date]
-- Creating a Date Table in DAX (if not available from source)
Calendar =
VAR MinDate = MIN('Orders'[Order Date])
VAR MaxDate = MAX('Orders'[Order Date])
RETURN
ADDCOLUMNS(
CALENDAR(DATE(YEAR(MinDate), 1, 1), DATE(YEAR(MaxDate), 12, 31)),
"Year", YEAR([Date]),
"Quarter", "Q" & FORMAT([Date], "Q"),
"Month", MONTH([Date]),
"Month Name", FORMAT([Date], "MMMM"),
"Year-Month", FORMAT([Date], "YYYY-MM"),
"Day of Week", WEEKDAY([Date]),
"Day Name", FORMAT([Date], "dddd"),
"Is Weekend", WEEKDAY([Date]) IN {1, 7}
)When a complex measure returns wrong results, break it into VAR steps and return each one individually to find the problematic step.
Debug Row Count =
COUNTROWS('Orders') & " rows in context"Debug Filters =
CONCATENATEX(
FILTERS('Products'[Category]),
'Products'[Category],
", "
)Get the full Power BI DAX Pattern Library and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.