pbPassingBI
/
DAX intermediate 9 min

DAX patterns worth memorising

Ranking, variables, safe division, and the functions you will reach for constantly.

What you'll be able to do
  • Use VAR to make measures readable and faster
  • Write ranking and top-N measures
  • Handle blanks and division safely

Variables

Profit Margin =
VAR TotalSales = SUM(Sales[Amount])
VAR TotalCost  = SUM(Sales[Cost])
RETURN DIVIDE(TotalSales - TotalCost, TotalSales)

Variables are evaluated once, where they're defined, and reused. That makes measures both faster and easier to read.

The subtle part: a variable captures the filter context at its point of definition. If you define a variable then wrap something in CALCULATE, the variable does not re-evaluate in the new context — which is sometimes exactly what you want and sometimes a bug.

DIVIDE, not slash

DIVIDE(numerator, denominator, [alternate]) returns blank (or your alternate) on divide-by-zero instead of an error. Always use it rather than /.

COALESCE(expr, 0) substitutes for blanks. Blank is not zero in DAX — blanks are excluded from visuals, which is often desirable, but breaks arithmetic when you didn't intend it.

Ranking

Product Rank =
RANKX(
    ALL(Product[Name]),
    [Total Sales],
    ,
    DESC,
    Dense
)

RANKX needs an explicit table to rank over — ALL(Product[Name]) ranks across all products regardless of the visual's filter on that column. Omitting ALL ranks within the current context, which usually returns 1 for every row and confuses people.

TOPN(10, Product, [Total Sales], DESC) returns a table of the top 10, useful inside CALCULATE.

Iterators and comparison

SUMX, AVERAGEX, MAXX, COUNTX iterate a table with row context. MAXX(Sales, Sales[Qty] * Sales[Price]) finds the largest line value — impossible with plain MAX.

CALCULATETABLE is CALCULATE for tables. VALUES returns distinct values of a column in the current context; DISTINCT is similar but excludes the blank row added by invalid relationships. HASONEVALUE guards against showing a measure when multiple values are selected.

Key points
  • VAR evaluates once and captures the context at definition point
  • Always DIVIDE instead of / ; blank is not zero
  • RANKX needs an explicit ALL table or every row ranks 1
Check yourself