0% found this document useful (0 votes)
239 views31 pages

Master DAX Measures: Jeffrey Wang Engineering Manager Microsoft Power BI

The document discusses how DAX measures work with filter context, focusing on how filter context impacts calculations, how filters are applied at the leaf nodes, and how bidirectional crossfiltering injects implicit filter expressions. It also contrasts Excel date/time functions, which operate on single values, with DAX time intelligence functions, which operate on filtered date columns between continuous dates.

Uploaded by

Me
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
239 views31 pages

Master DAX Measures: Jeffrey Wang Engineering Manager Microsoft Power BI

The document discusses how DAX measures work with filter context, focusing on how filter context impacts calculations, how filters are applied at the leaf nodes, and how bidirectional crossfiltering injects implicit filter expressions. It also contrasts Excel date/time functions, which operate on single values, with DAX time intelligence functions, which operate on filtered date columns between continuous dates.

Uploaded by

Me
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 31

Master DAX Measures

Jeffrey Wang
Engineering Manager
Microsoft Power BI
[email protected]
About me
• Started my BI career in 2002 soon after the dot-com bubble burst.
• Joined Microsoft in 2004 and stayed in BI engine ever since.
• Currently on the Desktop team in charge of the DAX engine.
• On the committee which invented DAX.
How do users use DAX in Power BI?
• Measures
• Calculated columns
• Calculated tables
• Row level security
Agenda
• Learn how DAX measures work
• Deep dive into filter context
• Make my measures return correct results
• Make my measures run fast
Filter Context
Row Context and Filter Context
• Row Context
• Calculated columns
• RLS
• Iteration functions
• Filter Context
• Power BI visuals
• Excel pivot tables
• Calculate functions
Filter contexts

C1 C2 C3 C4 C5 C6 C3 C4 C1 C5 C7 C1 C8 C9

Filter Context

* Filter columns must be columns in the model


A table scan semijoins with filter tables
• A table scan semijoins with filter tables with common columns
• In DAX, a table reference 'Table' is actually the result of virtual join (left outer
join) operations starting from the root table following all many-to-one
relationships
• DAX expression 'Sales' is a virtual join of 'Sales’ and all its related tables
'Sales'
LOJ 'Product' LOJ 'Product Subcategory' LOJ 'Product Category'
LOJ 'Date'
LOJ 'Customer'

Bidirectional crossfiltering injects implicit
filter expression
• For a slicer on a column from the 'Product' table to filter the
'Customer' table when bidirectional crossfiltering is enabled, DAX
Engine injects a filter right before the 'Customer' table is scanned
that’s equivalent to
CalculateTable('Customer', Summarize('Sales', 'Customer’[CustomerKey]))
Filter contexts apply to leaf nodes
• First filter, then calculate
• All related filters are applied
Calculate
• Multiple filters on the same
column are effectively ...
intersected + Filter1 FilterN

Filter first, calculate next


• In contrast, Filter function
performs post filtering - x
semantically
/

Filters in filter
context apply to
leaf nodes
How Does Filter Context Work?
Calculate(SumX(Filter(FactSales, [SalesQuantity] > 1000), [SalesAmount]), Date[Year] = 2011)
Order of operations
Sales Product
Date Product Key Product Key

Date Date Name

Month Amount

Year Cost

• [Profit Margin] =
(Sum(Sales[Amount]) – Sum(Sales[Cost])) / Sum(Sales[Amount])
• Calculate([Profit Margin], 'Product'[Name] = "P1")
DAX functions that work with
filter context
DAX was inspired by existing programming
languages
• Excel formulas – math and trigonometry, statistical, date/time, text,
logical, information, financial
• SQL – relational algebra operations
• MDX – measures, implicit join
DAX functions from Excel
• +, -, *, /, ^, =, >, <, >=, <=, <>, &, DateValue, Day, EDate, EOMonth, Hour, Minute,
Month, Now, Second, Time, TimeValue, Today, Weekday, WeekNum, Year,
YearFrac, Date, IsBlank, IsError, IsLogical, IsNonText, IsNumber, IsText, IsEven,
IsOdd, And, False, If, IfError, Not, Or, Switch, True, Abs, Ceiling, ISO.Ceiling, Exp,
Fact, Floor, Int, Ln, Log, Log10, Mod, MRound, Pi, Power, Quotient, Rand,
RandBetween, Round, RoundDown, RoundUp, Sign, Sqrt, Trunc, Acos, Acosh, Acot,
Acoth, Asin, Asinh, Atan, Atanh, Combin, Cos, Cosh, Cot, Coth, Degrees, Even, Odd,
Permut, Radians, Sin, Sinh, SqrtPi, Tan, Tanh, Chisq.Dist, Chisq.Dist.Rt, Chisq.Inv,
Chisq.Inv.Rt, Combina, Confidence.Norm, Confidence.T, Expon.Dist, GCD, LCM,
Norm.Dist, Norm.Inv, Norm.S.Dist, Norm.S.Inv, Poisson.Dist, Beta.Dist, Beta.Inv,
T.Dist.2T, T.Dist, T.Dist.Rt, T.Inv.2T, T.Inv, Blank, Concatenate, Exact, Find, Fixed, Left,
Len, Lower, Mid, Replace, Rept, Right, Search, Substitute, Format, Trim, Upper,
Value, Unicode, Unichar, XNPV, XIRR
DAX functions inspired by SQL
• Selection: Filter, IN, ContainsRow
• TopN: TopN, Sample, TopNSkip
• Projection/Rename: SelectColumns, AddColumns
• GroupBy – Distinct, Values, Summarize, GroupBy
• Aggregation functions: IsEmpty, ConcatenateX, Sum, SumX, Average, AverageA, AverageX, Count,
CountRows, CountA, CountAX, CountX, CountBlank, DistinctCount, DistinctCountNoBlank, Max, MaxX, MaxA,
Median, MedianX, Min, MinX, MinA, Percentile.Exc, Percentile.Inc, PercentileX.Exc, PercentileX.Inc, Rank.EQ,
RankX, Stdev.S, StdevX.S, StdevX.P, Stdev.P, Var.S, VarX.S, VarX.P, Var.P, Product, ProductX, Geomean,
GeomeanX, CurrentGroup
• Joins: CrossJoin, Generate, GenerateAll, NaturalLeftOuterJoin, NaturalInnerJoin, FullOuterJoin
• Set functions: Union, Intersect, Except
• Table construction:{}, Row, DataTable, GenerateSeries
• Fetch column value: Related, LookupValue
• Hierarchical functions: Path, PathItem, PathItemReverse, PathLength, PathContains
DAX functions inspired by MDX
• Filter context functions: IsCrossFiltered, HasOneValue, IsFiltered, HasOneFilter,
RemoveFilters, All, AllExcept, AllNoBlankRow, AllSelected, Calculate, CalculateTable,
Filters, Values, SelectedValue, TreatAs, UseRelationship, CrossFilter, KeepFilters,
IsInScope, NonVisual
• BI query functions: SummarizeColumns, Rollup, RollupGroup, RollupAddIsSubtotal,
RollupIsSubtotal, IsSubtotal, Ignore, AddMissingItems
• Time intelligence functions: DateAdd, FirstDate, LastDate, FirstNonBlank, LastNonBlank,
StartOfMonth, StartOfQuarter, StartOfYear, EndOfMonth, EndOfQuarter, EndOfYear,
DatesBetween, DatesInPeriod, ParallelPeriod, PreviousDay, PreviousMonth,
PreviousQuater, PreviousYear, NextDay, NextMonth, NextQuarter, NextYear, DatesMTD,
DatesQTD, DatesYTD, SamePeriodLastYear, TotalMTD, TotalQTD, TotalYTD,
OpeningBalanceMonth, OpeningBalanceQuarter, OpeningBalanceYear,
ClosingBalanceMonth, ClosingBalanceQuarter, ClosingBalanceYear
Convert Row Context to Filter Context
• Calculate/CalculateTable
• Convert all rows in row context into filters in filter context
• Add new filters
• Remove filters
• Replace existing filters
• [measure] := <expression> is actually Calculate(<expression>)
• All rows have already been converted to filters before <expression> is
evaluated
• 'Table'[Column] does not work at the top level of a measure expression
• Filter is an iteration function. It doesn’t change filter contexts.
Common DAX patterns that may
produce unexpected results
Set simple filters
• The following two ways of setting filters are different:
1. Calculate(Sum('Sales'[Sales Amount]), Geography[Country] = "United States")
2. Calculate(Sum('Sales'[Sales Amount]), Filter(Geography, [Country] = "United States"))

• Option 1 is equivalent to
1.1. Calculate(Sum('Sales'[Sales Amount]), Filter(All(Geography[Country]), [Country] = "United States"))

• Expressions affected by surrounding filters:


• CountRows(Geography)
• CountRows(Distinct(Geography[Country]))
• CountRows(Values(Geography[Country]))
• HasOneValue(Geography[Country])
• IsFiltered(Geography[Country])
• Sum('Sales'[Sales Amount]) is equivalent to SumX('Sales', [Sales Amount])

• Expressions not affected by surrounding filters:


• Filter(All(Geography), [Country] = "United States")
• All(Geography[Country])
Use DAX variables to avoid unexpected side
effects
• Using measures on the right-side of iterator functions (Filter, SumX, etc.) may pick up unexpected filters
Current Date = Max('Date'[Date])

YTD Sales =
Calculate(
[Total Sales],
Filter(All('Date'[Date]), Year([Date]) = Year([Current Date]) && [Date] <= [Current Date])
)
• Solution: Use variables to store measure values in the correct context
YTD Sales =
Var vCurrentDate = [Current Date]
Return
Calculate(
[Total Sales],
Filter(All('Date'[Date]), Year([Date]) = Year(vCurrentDate) && [Date] <= vCurrentDate)
)
Time Intelligence Functions
Excel date/time functions vs. DAX time
intelligence functions
• DAX stores dates as sequential numbers representing the number of days starting from 12/30/1899.
• Example: convert number of seconds into DateTime:
• Date(1899, 12, 30) + <number of seconds> / (24 * 60 * 60)
• Time(0, 0, <number of seconds>) has limitations
• Arithmetic operators and Excel functions operate on a single date/time value.
• Extract components from a date/time value
• Construct a date/time value from parts
• Convert a text value to a date/time value
• Shift a single date
• Often used to add calculated columns
• Can be done in M as well
• Don't use DAX in M editor
• DAX time intelligence functions operate on a filtered date column.
• Shift selected continuous dates
• Primarily used in measures
Excel date/time functions vs. DAX time
intelligence functions (Examples)
Scenario Right way Wrong way
7 days ago from today Today() - 7 DateAdd(Today(), -7, DAY)
1 month ago from today EDate(Today(), -1) DateAdd(Today(), -1, MONTH)
the last day of this month EOMonth(Today(), 0) EndOfMonth(Today())
the first day of this month Today() – Day(Today()) + 1 StartOfMonth(Today())

Scenario Use time intelligence functions Use Excel operators/functions


Flexible Inflexible
year over year sales SamePeriodLastYear, flexible Filter(…, [Calendar Year] = Values([Calendar Year])
– 1)

year to date sales TotalYTD, flexible Filter(…, [Date] <= Values([Date]) &&
[Date] >= Date(Year(Values([Date])), 1, 1))
DAX time intelligence function example:
SamePeriodLastYear

Year Quarter Date

2012 1 04/01/2012

X
2012 2 04/02/2012

2012 3 ...
06/30/2012
2012 4
2013 1
2013 2
2013 3
2013 4

Row Context Filter Context

Evaluation Context
DAX time intelligence functions shift
continuous dates
• Common error message
MdxScript(Model) (X, XX) Calculation error in measure 'XXX'[X]: Function
'DATEADD' only works with contiguous date selections.
• Examples
1. Multi-selection of years
2. Bi-directional cross-filtering to the Date table
• Time intelligence functions work on filtered date column.
Hidden date tables and DAX dot notation
• PowerBI automatically creates a hidden data table for each date/time
column
• A uni-direction relationship is created between the visible date/time
column and the hidden date table
• Users can access the columns in a hidden date table using DAX dot
notation through the visible date/time column
• [Order Date].[Date] is equivalent to Related('Hidden Table'[Date])
• [Order Date].[Year] is equivalent to Related('Hidden Table'[Year])
Common DAX patterns that
produce slow queries
DistinctCount with changing filters
• Calculate(DistinctCount('Sales'[CustomerKey]), Except(All('Product'),
'Product’))
• Calculate(DistinctCount('Sales'[CustomerKey]),
Filter(Values('Product'[Standard Cost]), [Standard Cost] > 100))
Avoid dense measures combined with
columns from different dimension tables
• BLANK value is your friend in BI queries.
• Examples of dense measures:
• [measure] = 1
• [measure] = Count('Sales'[ProductKey]) + 0
• [measure] = If ([Total Sales] <> 0, [Gross Margin] / [Total Sales], 0)
• The combination of many columns from different dimension tables
and a dense measure is a leading cause of out-of-memory errors.
Replace multiple instances of the same
measure by a variable
• [YoY growth] = Divide([CY Sales] – [LY Sales], [LY Sales])

You might also like