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
- Variables are evaluated once, where they are defined;
CALCULATEcannot change a variable's value. - Iterators create a row context; calling a measure inside one triggers context transition.
CALCULATEreplaces filters;KEEPFILTERSintersects them;FILTERhandles 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.
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.
| Iterator | Result |
|---|---|
SUMX, AVERAGEX, MINX, MAXX | Sum, average, minimum or maximum of a row-level expression |
COUNTX | Count of rows where the expression is not blank |
RANKX | The rank of the current item within a table |
CONCATENATEX | Text 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
| Function | Effect 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 REMOVEFILTERS | Remove filters from a table or column |
ALLEXCEPT ( table, col ) | Remove all filters on the table except the named columns |
ALLSELECTED | Keep filters from outside the visual, such as slicers, and ignore the visual's own rows |
CALCULATETABLE | The 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 )
)
)
| Function | Returns |
|---|---|
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.
| Function | Returns 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.
Total SalesusesSUMXover quantity times price.Product RankusesRANKX ( ALLSELECTED ( 'Product'[Product Name] ), [Total Sales] ); under a category row, the category filter still applies, so ranks restart per category.Previous Month SalesusesOFFSET ( -1, ... )on the Year Month column.Sales or AverageusesISINSCOPEto switch between a value and an average.
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."
DIVIDEbyCALCULATEwithREMOVEFILTERSon Category. - "Return last month's sales next to this month's."
OFFSET ( -1, ... )withORDERBYon the month column.
What to remember for the exam
- Variables are evaluated once, where they are defined;
CALCULATEcannot change a variable's value. - Iterators create a row context; calling a measure inside one triggers context transition.
CALCULATEreplaces filters;KEEPFILTERSintersects them;FILTERhandles row-level conditions.OFFSET,WINDOWandINDEXneed anORDERBYand can usePARTITIONBY.ISINSCOPEdetects hierarchy levels;HASONEVALUEandSELECTEDVALUEdetect a single selection.
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 asSalesVar?The variable was evaluated when it was defined, so
CALCULATEcannot change it. Put the measure insideCALCULATEinstead.Which function returns the previous row's value ordered by month?
OFFSETwith a delta of -1 and anORDERBYon the month column, used insideCALCULATE.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.