Implement and Manage Semantic Models · Topic 3 of 6

DAX Variables, Iterators, Filters and Windows

Write DAX measures with variables, iterators like SUMX and RANKX, CALCULATE filters, WINDOW and OFFSET, and information functions like ISINSCOPE.

  • 5 min
In a nutshell
  • Variables are evaluated once, where they are defined; CALCULATE cannot change a variable's value.
  • Iterators create a row context; calling a measure inside one triggers context transition.
  • CALCULATE replaces filters; KEEPFILTERS intersects them; FILTER handles row-level conditions.

What it is

DAX measures are formulas that a semantic model evaluates in the filter context of each visual cell. The DP-600 outline names five groups of DAX skills: variables, iterators, table filtering, windowing and information functions.

The exam shows a requirement and asks you to choose, complete or fix a measure. Knowing what each function does to the filter context is more important than memorizing long formulas.

Visual cellFilter contextslicers, rows, columnsCALCULATEchanges filtersMeasure result

How it works

Variables

VAR stores a value or a table; RETURN gives the result. Variables make a measure easier to read, and each one is evaluated only once.

Margin % =
VAR SalesAmt = [Total Sales]
VAR CostAmt = [Total Cost]
RETURN
    DIVIDE ( SalesAmt - CostAmt, SalesAmt )

A variable is evaluated where it is defined, not where it is used. CALCULATE ( SalesAmt, REMOVEFILTERS ( 'Product' ) ) still returns the filtered value, because SalesAmt was already computed.

Iterators

An iterator walks a table row by row in a row context, evaluates an expression for each row, then aggregates.

IteratorResult
SUMX, AVERAGEX, MINX, MAXXSum, average, minimum or maximum of a row-level expression
COUNTXCount of rows where the expression is not blank
RANKXThe rank of the current item within a table
CONCATENATEXText values joined with a separator
Sales Amount = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] )

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

When an iterator calls a measure, such as SUMX ( Customer, [Total Sales] ), each row's context is turned into a filter. This context transition is what lets the measure return each customer's own sales.

Table filtering with CALCULATE

FunctionEffect on filters
CALCULATE ( m, 'Product'[Color] = "Red" )Replaces any filter on Color with Red
KEEPFILTERS ( 'Product'[Color] = "Red" )Adds Red on top of existing Color filters
FILTER ( table, condition )Returns rows that meet a row-level condition
ALL and REMOVEFILTERSRemove filters from a table or column
ALLEXCEPT ( table, col )Remove all filters on the table except the named columns
ALLSELECTEDKeep filters from outside the visual, such as slicers, and ignore the visual's own rows
CALCULATETABLEThe table version of CALCULATE
% of All Categories =
DIVIDE (
    [Total Sales],
    CALCULATE ( [Total Sales], REMOVEFILTERS ( 'Product'[Category] ) )
)

Large Order Sales =
CALCULATE (
    [Total Sales],
    FILTER ( Sales, Sales[Quantity] * Sales[Net Price] > 1000 )
)

A simple column condition is enough for Red. A condition that multiplies two columns needs FILTER over the table.

Windowing functions

WINDOW, OFFSET and INDEX return rows relative to the current one, ordered by ORDERBY and optionally grouped by PARTITIONBY.

Previous Month Sales =
CALCULATE (
    [Total Sales],
    OFFSET ( -1, ALLSELECTED ( 'Date'[Year Month] ), ORDERBY ( 'Date'[Year Month], ASC ) )
)

Running Total =
CALCULATE (
    [Total Sales],
    WINDOW (
        1, ABS, 0, REL,
        ALLSELECTED ( 'Date'[Year Month] ),
        ORDERBY ( 'Date'[Year Month], ASC )
    )
)
FunctionReturns
OFFSET ( n, ... )The row n positions before (negative) or after (positive) the current row
WINDOW ( from, type, to, type, ... )A range of rows; ABS counts from the start, REL from the current row
INDEX ( n, ... )The row at an absolute position, such as the first or last

Information functions

Information functions test the context or a value instead of calculating.

FunctionReturns TRUE when
ISBLANK ( x )The value is blank
HASONEVALUE ( col )Exactly one value of the column is in the filter context
ISFILTERED ( col )The column is filtered directly
ISCROSSFILTERED ( col )The column is filtered directly or through a related table
ISINSCOPE ( col )The column is a grouping level in the current visual row
Sales or Average =
IF (
    ISINSCOPE ( 'Product'[Product Name] ),
    [Total Sales],
    AVERAGEX ( VALUES ( 'Product'[Product Name] ), [Total Sales] )
)

ISINSCOPE is the right test for hierarchy levels in a matrix. SELECTEDVALUE ( col, alternate ) is the short way to read a single selected value.

A worked example

A matrix shows categories and products. The business wants each product's sales, its rank within its category, last month's sales, and the category average on category rows.

  1. Total Sales uses SUMX over quantity times price.
  2. Product Rank uses RANKX ( ALLSELECTED ( 'Product'[Product Name] ), [Total Sales] ); under a category row, the category filter still applies, so ranks restart per category.
  3. Previous Month Sales uses OFFSET ( -1, ... ) on the Year Month column.
  4. Sales or Average uses ISINSCOPE to switch between a value and an average.
Exam tip

When a measure "should ignore the product filter but keep the slicer on year", think REMOVEFILTERS or ALL on the product columns only, or ALLSELECTED.

How the exam asks about this

  • "Calculate revenue from quantity and unit price on each row." SUMX ( Sales, Sales[Quantity] * Sales[Unit Price] ).
  • "Show the share of each category in the total of all categories." DIVIDE by CALCULATE with REMOVEFILTERS on Category.
  • "Return last month's sales next to this month's." OFFSET ( -1, ... ) with ORDERBY on the month column.

What to remember for the exam

  • Variables are evaluated once, where they are defined; CALCULATE cannot change a variable's value.
  • Iterators create a row context; calling a measure inside one triggers context transition.
  • CALCULATE replaces filters; KEEPFILTERS intersects them; FILTER handles row-level conditions.
  • OFFSET, WINDOW and INDEX need an ORDERBY and can use PARTITIONBY.
  • ISINSCOPE detects hierarchy levels; HASONEVALUE and SELECTEDVALUE detect a single selection.
Watch out

FILTER ( Sales, ... ) over a whole fact table is far slower than a column condition such as 'Product'[Color] = "Red". Use FILTER only when the condition really needs the row.

Common mistakes

Changing filters around a variable. Wrapping an already evaluated variable in CALCULATE does nothing. Put the expression itself inside CALCULATE.

Using ISFILTERED to detect a matrix level. A slicer can filter a column that is not on the rows. ISINSCOPE tests the grouping level itself.

Dividing with /. Dividing by zero returns infinity or NaN, which looks wrong in a visual. DIVIDE returns blank or an alternate value instead.

Check yourself

  • Why does CALCULATE ( SalesVar, REMOVEFILTERS ( 'Product' ) ) return the same value as SalesVar?

    The variable was evaluated when it was defined, so CALCULATE cannot change it. Put the measure inside CALCULATE instead.

  • Which function returns the previous row's value ordered by month?

    OFFSET with a delta of -1 and an ORDERBY on the month column, used inside CALCULATE.

  • What is context transition?

    When a measure is evaluated inside a row context, such as in SUMX, the current row becomes a filter context for that measure.

Topic 3 of 6 in Implement and Manage Semantic Models

Test yourself on Implement and Manage Semantic Models

The full Microsoft DP-600 question bank has 648 questions, with timed practice exams and an explanation for every answer.

This study guide is independent and is not affiliated with, endorsed by, or sponsored by Microsoft. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.