Power BI DAX Reference Guide

25 DAX Measures Every Power BI Developer Needs

DAX (Data Analysis Expressions) is the formula language that powers every calculation in Power BI. While the UI lets you drag and drop fields, the real intelligence — YoY growth, running totals, dynamic rankings, KPI status — all comes from well-crafted DAX measures.

This guide is a copy-paste-ready reference library of the 25 DAX measures I use on almost every client project. Each measure includes a clean implementation, an explanation of what it does, and notes on where to use it.

📋
Before You Start — Best Practice

Store all your measures in a dedicated Measures Table. Right-click in the Fields pane → Enter Data → create a blank table called _Measures. This keeps your model organised and makes every measure easy to find.

Category 1 — Core Revenue Measures (1–5)

These five measures are the foundation of almost every sales or financial dashboard. Build these first — everything else references them.

Measure 1 — Total Revenue

DAX
Total Revenue =
SUMX(
    FactSales,
    FactSales[Quantity] * FactSales[UnitPrice]
)

Why SUMX instead of SUM? SUMX iterates row by row and multiplies before summing — giving you the correct result even when discounts or currency conversions apply per row. SUM of a pre-calculated column works too, but SUMX is more flexible and avoids redundant calculated columns.

Measure 2 — Total Cost (COGS)

DAX
Total Cost =
SUMX(
    FactSales,
    FactSales[Quantity] * RELATED(DimProduct[UnitCost])
)

RELATED() fetches the unit cost from the related DimProduct table for each row in FactSales. This works because of the many-to-one relationship between FactSales and DimProduct.

Measure 3 — Gross Profit

DAX
Gross Profit =
[Total Revenue] - [Total Cost]

Measure 4 — Gross Margin %

DAX
Gross Margin % =
DIVIDE(
    [Gross Profit],
    [Total Revenue],
    0
)
💡
Always Use DIVIDE() — Never the / Operator

The / operator throws a divide-by-zero error when the denominator is blank or zero. DIVIDE(numerator, denominator, alternateResult) handles this gracefully — returning 0, BLANK(), or any value you choose. This is one of the most important DAX habits to build early.

Measure 5 — Average Order Value

DAX
Average Order Value =
DIVIDE(
    [Total Revenue],
    DISTINCTCOUNT(FactSales[OrderID]),
    0
)

Category 2 — Time Intelligence (6–12)

Time intelligence is where DAX truly shines. These measures require a proper Date dimension table marked as a Date Table in Power BI (right-click the date table → Mark as date table).

Measure 6 — Revenue MTD

DAX
Revenue MTD =
TOTALMTD(
    [Total Revenue],
    DimDate[Date]
)

Returns the cumulative revenue from the start of the current month to the currently selected date. Use this in KPI cards to show month-to-date performance.

Measure 7 — Revenue QTD

DAX
Revenue QTD =
TOTALQTD(
    [Total Revenue],
    DimDate[Date]
)

Measure 8 — Revenue YTD

DAX
Revenue YTD =
TOTALYTD(
    [Total Revenue],
    DimDate[Date],
    "31 Mar"  -- Optional: fiscal year end date (remove for calendar year)
)

The third argument lets you define a custom fiscal year end. "31 Mar" means the fiscal year runs April–March (common in India). Remove it entirely for a standard January–December year.

Measure 9 — Revenue Last Year (LY)

DAX
Revenue LY =
CALCULATE(
    [Total Revenue],
    SAMEPERIODLASTYEAR(DimDate[Date])
)

Measure 10 — Revenue YoY Growth %

DAX
Revenue YoY % =
DIVIDE(
    [Total Revenue] - [Revenue LY],
    [Revenue LY],
    BLANK()
)

Returns BLANK() instead of 0 when there is no prior-year data — this prevents misleading 0% growth from appearing in charts when a period simply has no comparison.

Measure 11 — Revenue vs Target

DAX
Revenue vs Target =
[Total Revenue] - [Sales Target]

Revenue vs Target % =
DIVIDE(
    [Revenue vs Target],
    [Sales Target],
    0
)

Measure 12 — Previous Month Revenue

DAX
Revenue Previous Month =
CALCULATE(
    [Total Revenue],
    PREVIOUSMONTH(DimDate[Date])
)

Revenue MoM % =
DIVIDE(
    [Total Revenue] - [Revenue Previous Month],
    [Revenue Previous Month],
    BLANK()
)

Category 3 — Running Totals (13–14)

Measure 13 — Running Total Revenue

DAX
Running Total Revenue =
CALCULATE(
    [Total Revenue],
    FILTER(
        ALLSELECTED(DimDate[Date]),
        DimDate[Date] <= MAX(DimDate[Date])
    )
)

ALLSELECTED respects the user's date slicer selection while still accumulating values up to each date point. This is the correct running total pattern — not ALL(), which would ignore slicers entirely.

Measure 14 — Running Total % of Grand Total

DAX
Running Total % =
DIVIDE(
    [Running Total Revenue],
    CALCULATE([Total Revenue], ALLSELECTED(DimDate[Date])),
    0
)

Category 4 — Rankings (15–17)

Measure 15 — Product Rank by Revenue

DAX
Product Rank =
RANKX(
    ALLSELECTED(DimProduct[ProductName]),
    [Total Revenue],
    ,
    DESC,
    DENSE
)

DENSE ranking means no gaps in rank numbers (1, 2, 3 — not 1, 2, 4 when there's a tie). ALLSELECTED ensures the rank updates correctly when the user applies slicers.

Measure 16 — Top N Filter

DAX
Top N Revenue =
VAR N    = SELECTEDVALUE(TopNTable[N], 10)
VAR Rank = [Product Rank]
RETURN
IF(Rank <= N, [Total Revenue], BLANK())

Create a disconnected TopNTable with values like {5, 10, 20} and a slicer on it. This measure then dynamically filters to show only the top N products — without any hardcoded number.

Measure 17 — Customer Rank by Revenue

DAX
Customer Rank =
RANKX(
    ALLSELECTED(DimCustomer[CustomerName]),
    [Total Revenue],
    ,
    DESC,
    DENSE
)

Category 5 — Share & Ratio Measures (18–20)

Measure 18 — % of Total Sales

DAX
% of Total Sales =
DIVIDE(
    [Total Revenue],
    CALCULATE([Total Revenue], ALL(DimProduct)),
    0
)

ALL(DimProduct) removes any product filter, so the denominator is always the grand total — regardless of which product is in context. This gives each product its true percentage share.

Measure 19 — % of Category Sales

DAX
% of Category Sales =
DIVIDE(
    [Total Revenue],
    CALCULATE(
        [Total Revenue],
        ALLEXCEPT(DimProduct, DimProduct[Category])
    ),
    0
)

ALLEXCEPT removes all filters on DimProduct except Category — so the denominator is the category total. Each product shows its share within its own category.

Measure 20 — Transaction Count

DAX
Transaction Count =
COUNTROWS(FactSales)

Unique Customers =
DISTINCTCOUNT(FactSales[CustomerID])

Unique Products Sold =
DISTINCTCOUNT(FactSales[ProductID])

Category 6 — KPI & Conditional Logic (21–23)

Measure 21 — KPI Status (RAG)

DAX
KPI Status =
VAR Achievement = [Revenue vs Target %]
RETURN
SWITCH(
    TRUE(),
    Achievement >= 0,     "🟢 On Track",
    Achievement >= -0.10, "🟡 At Risk",
    "🔴 Behind"
)

-- Colour version for conditional formatting
KPI Colour =
VAR Achievement = [Revenue vs Target %]
RETURN
SWITCH(
    TRUE(),
    Achievement >= 0,     "#10B981",   -- green
    Achievement >= -0.10, "#F59E0B",   -- amber
    "#EF4444"                                -- red
)

Use KPI Status in a table or matrix to show text labels. Use KPI Colour as a dynamic field-value colour in card or table conditional formatting — creating a real RAG (Red-Amber-Green) dashboard.

Measure 22 — YoY Arrow Indicator

DAX
YoY Arrow =
VAR Growth = [Revenue YoY %]
RETURN
IF(
    ISBLANK(Growth),
    "—",
    IF(Growth >= 0, "▲ ", "▼ ") &
    FORMAT(ABS(Growth), "0.0%")
)

YoY Colour =
IF([Revenue YoY %] >= 0, "#10B981", "#EF4444")

Measure 23 — Dynamic KPI Card Title

DAX
Dynamic Title =
VAR SelectedYear  = SELECTEDVALUE(DimDate[Year], "All Years")
VAR SelectedRegion= SELECTEDVALUE(DimRegion[RegionName], "All Regions")
RETURN
"Revenue — " & SelectedYear & " | " & SelectedRegion

Use this in a card visual's subtitle or title field. The text updates automatically as the user selects different slicers — eliminating the need for static titles that go out of date.

Category 7 — Utility Measures (24–25)

Measure 24 — Last Data Refresh Date

DAX
Last Sale Date =
"Data as of: " &
FORMAT(
    MAX(FactSales[SaleDate]),
    "DD MMM YYYY"
)

-- Alternative: show last refresh timestamp
Last Refreshed =
"Last refreshed: " &
FORMAT(
    NOW(),
    "DD MMM YYYY, hh:mm AM/PM"
)

Always add a "data as of" label to your dashboard so users know how fresh the data is. Place it in a small text card at the bottom of every report page.

Measure 25 — Selected Period Label

DAX
Selected Period =
VAR MinDate = FORMAT(MIN(DimDate[Date]), "DD MMM YYYY")
VAR MaxDate = FORMAT(MAX(DimDate[Date]), "DD MMM YYYY")
RETURN
IF(
    MinDate = MaxDate,
    MinDate,
    MinDate & " to " & MaxDate
)

This measure reads the current date slicer selection and displays it as human-readable text — perfect for report headers, export filenames, or email subject lines when embedding reports.

Quick Reference — All 25 Measures

#MeasureCategoryKey Function
1Total RevenueCoreSUMX
2Total CostCoreSUMX + RELATED
3Gross ProfitCoreMeasure reference
4Gross Margin %CoreDIVIDE
5Average Order ValueCoreDIVIDE + DISTINCTCOUNT
6Revenue MTDTime IntelligenceTOTALMTD
7Revenue QTDTime IntelligenceTOTALQTD
8Revenue YTDTime IntelligenceTOTALYTD
9Revenue LYTime IntelligenceSAMEPERIODLASTYEAR
10Revenue YoY %Time IntelligenceDIVIDE
11Revenue vs TargetTime IntelligenceMeasure reference
12Revenue Previous MonthTime IntelligencePREVIOUSMONTH
13Running TotalRunning TotalsCALCULATE + ALLSELECTED
14Running Total %Running TotalsDIVIDE + ALLSELECTED
15Product RankRankingsRANKX
16Top N FilterRankingsRANKX + SELECTEDVALUE
17Customer RankRankingsRANKX
18% of Total SalesShare & RatioDIVIDE + ALL
19% of Category SalesShare & RatioDIVIDE + ALLEXCEPT
20Transaction CountShare & RatioCOUNTROWS + DISTINCTCOUNT
21KPI Status (RAG)KPI & ConditionalSWITCH + TRUE()
22YoY Arrow IndicatorKPI & ConditionalIF + FORMAT
23Dynamic TitleKPI & ConditionalSELECTEDVALUE
24Last Refresh DateUtilityMAX + FORMAT
25Selected Period LabelUtilityMIN + MAX + FORMAT
🚀
Pro Tip: Use VAR…RETURN in Every Complex Measure

Whenever a measure references another measure more than once, store it in a VAR. DAX evaluates variables only once — reusing the same measure expression directly causes it to be recalculated every time it appears, which significantly slows down large models.


Ankit Kumar

Power BI Developer · Data Analyst · ETLGuru.in

Ankit Kumar is a Data Analyst and founder of Pyivot Solutions with 5+ years of experience building production Power BI dashboards for manufacturing, trading, and e-commerce businesses. He has delivered 25+ Power BI projects with measurable business impact across India.