0% found this document useful (0 votes)
132 views113 pages

DAX Zero To Hero

Power BI

Uploaded by

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

DAX Zero To Hero

Power BI

Uploaded by

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

GrowTechie

DAX: From Zero To Hero

Swipe Right

@ramakrushnamohapatra
GrowTechie

The DAX Language

1. Language Of BI

● Power BI
● Analytics Service Tabular
● Power Pivot

1. DAX Is Simple, But Its not easy

1. New Programming Concepts and Patterns


GrowTechie

What Is DAX ?

1. Programming language
• Power BI
• Analysis Services Tabular
• Power Pivot
1. Resembles Excel
• Because it was born with PowerPivot
• Important differences
• No concept of «row» and «column»
• Different type system
1. Many new functions
2. Designed for data models and business
GrowTechie

Functional Language
DAX is a functional language, the execution flows with function calls, here is
an example of a DAX formula.

=SUMX (FILTER (
VALUES ( 'Date'[Year] ),
'Date'[Year] < 2005
),
IF (
'Date'[Year] >= 2000,
[Sales Amount] * 100,
[Sales Amount] * 90
))
GrowTechie

If it is not formatted, it is not DAX


Code formatting is of paramount importance in DAX.
=SUMX(FILTER(VALUES('Date'[Year]),'Date'[Year]<2005),IF('Date'[Year]>=2000,[Sales
Amount]*100,[Sales Amount]*90)

=SUMX (FILTER (
VALUES ( 'Date'[Year] ),
'Date'[Year] < 2005
),
IF ( 'Date'[Year] >= 2000,
[Sales Amount] * 100,
[Sales Amount] * 90
))
GrowTechie

DAX Data Types

1. Numeric types

• Integer (64 bit)


• Decimal (floating point)
• Currency (money)
• Date (DateTime)
• TRUE / FALSE (Boolean)

2. Other types

• String
• Binary Objects
GrowTechie

DAX Type Handling

1. Operator Overloading

• Operators are not strongly typed


• The result depends on the inputs

1. Example:

• "4" + "8" = 12
• 4 & 8 = "48"

1. Conversion happens when needed

• Pay attention to undesired conversions


GrowTechie

DateTime

1. Floating point value

1. Integer part
• Number of days after December, 30, 1899

1. Decimal part
• Seconds: 1 / ( 24 * 60 * 60 )
1. DateTime Expressions
• Date + 1 = The day after
• Date - 1 = The day before
GrowTechie

Calculated Columns

1. Columns computed using DAX

1. Always computed row by row

1. Product[Price] means

• The value of the Price column (explicit)


• In the Product table (explicit, optional)
• For the current row (implicit)
• Different for each row
GrowTechie

Column References
1. The general format to reference a column

• 'TableName'[ColumnName]

1. Quotes can be omitted

• If TableName does not contain spaces


• Do it: omit quotes if there are no spaces in table name

1. TableName can be omitted

• Current table is searched for ColumnName


• Don’t do it, harder to understand
GrowTechie

Measures
1. Written using DAX

1. Do not work row by row

1. Instead, use tables and aggregators

1. Do not have the «current row» concept

1. Examples
• GrossMargin
• is a calculated column
• but can be a measure, too
• GrossMargin %
• must be a measure
GrowTechie

Naming Convention
1. Measures should not belong to a table

• Avoid table name


• [Margin%] instead of Sales[Margin%]
• Easier to move to another table
• Easier to identify as a measure

1. Use this syntax when to reference:

• Columns → Table[Column]
• Measures → [Measure]
GrowTechie

Measures vs Calculated Columns


1. Use a column when
• Need to slice or filter on the value

1. Use a measure
• Calculate percentages
• Calculate ratios
• Need complex aggregations

1. Space and CPU usage


• Columns consume memory in the model
• Measures consume CPU at query time
GrowTechie

Aggregation Functions
1. Useful to aggregate values
• SUM
• AVERAGE
• MIN
• MAX

1. Aggregate only one column


• SUM ( Orders[Price] )
• SUM ( Orders[Price] * Orders[Quantity] )
GrowTechie

The «X» Aggregation Functions


1. Iterators: useful to aggregate formulas
• SUMX
• AVERAGEX
• MINX
• MAXX

1. Iterate over the table and evaluate the expression for each
row

1. Always receive two parameters


• Table to iterate
• Formula to evaluate for each row
GrowTechie

Example Of SUMX
For each row in the Sales table, evaluates the formula, then sum up all the results.
Inside the formula, there is a «current row».
GrowTechie

SUM or SUMX?
Actually, SUM is nothing but syntax sugar for SUMX

--
-- This is the compact format for a SUM
--
SUM ( Sales[Quantity] )
--
-- Internally, this is translated into
--
SUMX (
Sales,
Sales[Quantity]
)
GrowTechie

IN Operator

1. Verify if the result of an expression is included in a list of values:

Customer[State] IN { "WA", "NY", "CA" }

1. It would require multiple OR conditions otherwise:

Customer[State] = "WA"
|| Customer[State] = "NY"
|| Customer[State] = "CA"
GrowTechie

The DIVIDE Function


Divide is useful to avoid using IF inside an expression to check for zero
denominators. It is also faster than using IF.

IF (
Sales[SalesAmount] <> 0,
Sales[GrossMargin] / Sales[SalesAmount],
0)

You can write it better with DIVIDE

DIVIDE (
Sales[GrossMargin],
Sales[SalesAmount],
0)
GrowTechie

Using Variables
Very useful to avoid repeating subexpressions in your code.

VAR

TotalQuantity = SUM ( Sales[Quantity] )

RETURN

IF (
TotalQuantity > 1000,
TotalQuantity * 0.95,
TotalQuantity * 1.25
)
GrowTechie

Relational Functions
1. RELATED

• Follows relationships and returns the value of a column

1. RELATEDTABLE

• Follows relationships and returns all the rows in relationship


with the current one

1. It doesn’t matter how long the chain of relationships is

• All the relationships must be in the same direction


GrowTechie

Some functions return tables instead of values

Table Functions
GrowTechie

Table Functions
1. Basic functions that work and/or return full tables

• FILTER
• ALL
• VALUES / DISTINCT
• RELATEDTABLE
• ADDCOLUMNS / SUMMARIZE

1. They are used very often in DAX – their knowledge is required


2. Their result is often used in other functions
3. They can be combined together to form complex expressions
4. We will discover many other table functions later in the course
GrowTechie

Filtering A Table
GrowTechie

The FILTER Function

1. FILTER

• Adds a new condition


• Restricts the number of rows of a table
• Returns a table
• Can be iterated by an «X» function

1. Needs a table as input


2. The input can be another FILTER
GrowTechie

Ignoring Filters
GrowTechie

The ALL Function


1. ALL

• Returns all the rows of a table


• Ignores any filter
• Returns a table
• That can be iterated by an «X» function

1. Needs a table as input


2. Can be used with a single column

• ALL ( Customers[CustomerName] )
• The result contains a table with one column
GrowTechie

ALL With Many Columns


Returns a table with all the values of all the columns passed as parameters.

COUNTROWS (
ALL (
Orders[Channel],
Orders[Color], Columns of the
same table
Orders[Size]
)
)
GrowTechie

Mixing Filters

1. Table functions can be mixed

1. Each one requires a table

1. Each one returns a table

1. FILTER ( ALL ( Table ), Condition )

• Puts a filter over the entire table


• Ignores the current filter context
GrowTechie

Mixing Filters
GrowTechie

DISTINCT

Returns the unique values of a column, only the ones visible in the current filter
context.

NumOfProducts :=

COUNTROWS (

DISTINCT ( Product[ProductCode] )

)
GrowTechie

How Many Values For A Column?

Returns the unique values of a column, only the ones visible in the current filter
context.

Tables targets of a relationship might contain an additional blank row,


created by DAX to guarantee referential integrity.
GrowTechie

VALUES
Returns the unique values of a column, only the ones visible in the current filter
context, including the additional blank row if it is visible in the filter context.

NumOfProducts :=

COUNTROWS (

VALUES ( Product[ProductCode] )

)
GrowTechie

Counting Different Values


ALL returns the additional blank row, if it exists. ALLNOBLANKROW omits it.

Note the difference among


o DISTINCT
o VALUES
o ALL
o ALLNOBLANKROW
GrowTechie

ALLSELECTED
ALLSELECTED returns the elements of a table as they are visible outside of the
current visual, be either a pivot table in Excel or a visual in Power BI.
GrowTechie

RELATEDTABLE
Returns a table with all the rows related with the current one.

NumOfProducts =

COUNTROWS (

RELATEDTABLE ( Product )

)
GrowTechie

ADDCOLUMNS
Adds one or more columns to a table expression, keeping all existing columns.
It is an iterator, therefore you can access columns of the iterated table
ColorsAndSales

ADDCOLUMNS (

VALUES ( 'Product'[Color] ), "Sales",

SUMX (

RELATEDTABLE ( Sales ),

Sales[Quantity] * Sales[Net Price]

))
GrowTechie

Tables with one row and one column


When a table contains ONE row and ONE column, you can treat is as a scalar val

Sel Category :=

"You selected: " &

IF (
HASONEVALUE ( 'Product Category'[Category] ),

VALUES ( 'Product Category'[Category] ),

"Multiple values"
)
GrowTechie

SELECTEDVALUE
SELECTEDVALUE is a convenient function that simplifies retrieving the value of a
column, when only one value is visible.

SELECTEDVALUE (
'Product Category'[Category],
"Multiple values"
)

Equivalent to:
IF (
HASONEVALUE ( 'Product Category'[Category] ),
VALUES ( 'Product Category'[Category] ),
"Multiple values"
)
GrowTechie

Table variables
A variable can contain either a scalar value or a table. Using table variables greatly
helps in splitting complex expressions.
VAR
SalesGreaterThan10 = FILTER ( Sales, Sales[Quantity] > 10 )

RETURN

SUMX (
FILTER (
SalesGreaterThan10,
RELATED ( Product[Color] ) = "Red"
),

Sales[Amount]
)
GrowTechie

Let us take a look at how DAX works

Evaluation Contexts
GrowTechie

Evaluation contexts

1. Evaluation contexts are the pillars of DAX

1. Simple concepts, hard to learn

1. At the beginning, they looks very easy

1. Using them, complexity arises

1. The devil is in the details


GrowTechie

What is an evaluation context?

TotalSales := SUMX ( Sales, Sales[Quantity] * Sales[Net Price] )


GrowTechie

Filter context in a pivot table


GrowTechie

Example of a filter context


GrowTechie

Filter context in Power BI


GrowTechie

Filter context
1. Defined by
• Row Selection
• Column Selection
• Report Filters
• Slicers Selection

1. Rows outside of the filter context


• Are not considered for the computation

1. Defined automatically by the client, tool

1. Can also be created with specific functions


GrowTechie

Row context
1. Defined by
• Calculated column definition
• Defined automatically for each row
• Row Iteration functions
• SUMX, AVERAGEX …
• All «X» functions and iterators
• Defined by the user formulas

2. Needed to evaluate column values, it is the concept of


“current row”
GrowTechie

SUMX ( Orders, Orders[Quantity]*Orders[Price] )


GrowTechie

There are always two contexts


1. Filter context
• Filters tables
• Might be empty
• All the tables are visible
• But this never happens in the real world
1. Row context
• Iterates rows
• For the rows active in the filter context
• Might be empty
• There is no iteration running
1. Both are «evaluation contexts»
GrowTechie

Filtering a table
GrowTechie

Ignoring filters
GrowTechie

Using RELATED in a row context


Starting from a row context, you can use RELATED to access columns in related
tables.

SUMX (
Sales,
Sales[Quantity]
* RELATED ( Products[ListPrice] )
* RELATED ( Categories[Discount] )
)

You need RELATED because the row


context is iterating the Sales table
GrowTechie

Nesting row contexts


Row contexts can be nested, on the same or on different tables.

SUMX (
Categories,
SUMX (
RELATEDTABLE ( Products ),
SUMX (
RELATEDTABLE ( Sales )

( Sales[Quantity] * Products[ListPrice] )
Three row contexts:
* Categories[Discount] • Categories
) ) ) • Products of category
• Sales of product
GrowTechie

Ranking by price

1. Create a calculated column

1. Ranks products by list price

1. Most expensive product is ranked 1


GrowTechie

Nesting row contexts


GrowTechie

Nesting row contexts


GrowTechie

Computing the correct rank


The correct solution requires to rank over the different prices, not the different
products. ALL with a column becomes very handy here.

Products[RankOnPrice] =
VAR CurrentListPrice = Products[ListPrice]
VAR AllPrices = ALL ( Products[ListPrice] )
RETURN
COUNTROWS (
FILTER (
AllPrices,
Products[ListPrice] > CurrentListPrice
)
)+1
GrowTechie

Evaluation contexts and relationships


GrowTechie

Filters and relationships


GrowTechie

Row context – multiple tables


Row Context does not propagate over relationships
GrowTechie

RELATED
RELATED ( table[column] )
• Opens a new row context on the target table
• Following relationships
GrowTechie

RELATEDTABLE
1. RELATEDTABLE ( table )
• Filters the parameter table
• Returns only rows related with the current one
1. It is the companion of RELATED
GrowTechie

Filter context – many tables


GrowTechie

Filters and relationships


GrowTechie

Bidirectional cross-filter

1. Choose the propagation of the filter context


• Single: one to many propagation
• Both: filter context propagates both ways

1. Not available in Excel, only Analysis Services and Power BI

1. Beware of several details


• Performance degradation
• Filtering is active when the “many” side is cross-filtered, numbers might
be hard to read for certain measures
• Ambiguity might appear in the model
GrowTechie

The most important DAX function

CALCULATE
GrowTechie

CALCULATE syntax
Filters are evaluated in the outer filter context, then combined together in AND, and
finally used to build a new filter context into which DAX evaluates the expression.
GrowTechie

CALCULATE examples
Compute the sum of sales where the price is greater than $100.00.
GrowTechie

Filters are tables


Each filter is a table. Boolean expressions are nothing but shortcuts for table
expressions.
GrowTechie

Let’s learn CALCULATE by using some demo

CALCULATE Examples
GrowTechie

CALCULATE examples
Compute the sales amount for all of the product colors, regardless of the user
selection.
GrowTechie

CALCULATE examples
Compute the sales amount for red products, regardless of user selection for color.
The filter context is applied on the entire model, products filter the Sales table, too.
GrowTechie

CALCULATE examples
Compute the sales amount for red and blue products, within the user selection for color.
GrowTechie

What is a filter context?


Compute the sales amount for red and blue products, within the user selection for color.
GrowTechie

Filter context definition


GrowTechie

Multiple conditions in CALCULATE


Multiple filter parameters in CALCULATE are intersected, generating a new filter
context that uses both filters at the same time.
GrowTechie

Intersection of filter context


Used by CALCULATE to put filters in AND
GrowTechie

Overwriting filter contexts


Nested CALCULATE do not intersect filters, they use another operator, called
OVERWRITE. In fact, the Yellow/Black filter wins against the Black/Blue one, being
the innermost. Yellow/Black overwrites Black/Blue.
GrowTechie

KEEPFILTERS
KEEPFILTERS retains the previous filters, instead of replacing them.
GrowTechie

CALCULATE operators

o Overwrite a filter context at the individual columns level

o Remove previously existing filters (ALL)

o Add filters (KEEPFILTERS)

o In DAX you work by manipulating filters with the following internal operators:
• INTERSECT (multiple filters in CALCULATE)
• OVERWRITE (nested CALCULATE)
• REMOVEFILTERS (using ALL)
• ADDFILTER (using KEEPFILTERS)
GrowTechie

KEEPFILTERS might be required, don’t filter the table!


KEEPFILTERS is required to keep the same semantics of the table filter. You obtain a similar
result by filtering the entire table. Filtering a table is a very bad practice.
GrowTechie

Aggregators in compact syntax


Aggregators in compact syntax are evaluated in the outer filter context
GrowTechie

Variables and evaluation contexts


Variables are computed in the evaluation where they are defined, not in the one where
they are used. CALCULATE cannot modify the value of a variable because it is already
computed.
GrowTechie

One more feature of CALCULATE

Context transition
GrowTechie

Context transition

o Calculate performs another task

o If executed inside a row context


• It takes the row context
• Transforms it into an equivalent filter context
• Applies it to the data model
• Before computing its expression

o Very important and useful feature


• Better to learn it writing some code…
GrowTechie

Context transition
GrowTechie

Unexpected results if there are duplicated rows


GrowTechie

Some notes on context transition


o It is invoked by CALCULATE

O It is expensive: don’t use it iterating large tables

O It does not filter one row, it filters all the identical rows

O It creates a filter context out of a row context

O It happens whenever there is a row context

O It transforms all the row contexts, not only the last one

O Row contexts are no longer available in CALCULATE


GrowTechie

Automatic CALCULATE
Whenever a measure is invoked, an automatic CALCULATE is added around the measure.
This is the reason why using [Measure] and Table[Column] as a standard is a best practice.

SUMX (
Orders,
[Sales Amount]
)
SUMX (
Orders,
CALCULATE ( [Sales Amount] )
)
GrowTechie

Time to start thinking in DAX

Working with iterators


GrowTechie

Computing max daily sales


O What is the maximum amount of sales in
one day?

O MAX is not enough

O Consolidate the daily amount and then find


the maximum value
GrowTechie

MIN-MAX sales per customer


Iterators can be used to compute values at a different granularity than the one set in the
report.

MinSalesPerCustomer :=
MINX ( Customer, [Sales Amount] )

MaxSalesPerCustomer :=
MAXX ( Customer, [Sales Amount] )
GrowTechie

Useful iterators
There are many useful iterators, they all behave the same way: iterate on a table, compute
an expression and aggregate its value.

MAXX
MINX
AVERAGEX
SUMX
PRODUCTX
CONCATENATEXVARX.P | .S
STDEVX.P | .S
MEDIANX
PERCENTILEX.EXC | .INC
GEOMEANX
GrowTechie

Useful iterators
There are many useful iterators, they all behave the same way: iterate on a table, compute
an expression and aggregate its value.

MAXX
MINX
AVERAGEX
SUMX
PRODUCTX
CONCATENATEXVARX.P | .S
STDEVX.P | .S
MEDIANX
PERCENTILEX.EXC | .INC
GEOMEANX
GrowTechie

Probably the most important table in your model

Building a date table


GrowTechie

Date table

1. Time intelligence needs a date table


•Built in DAX, Power Query, SQL
•DAX example: https://www.sqlbi.com/tools/dax-date-template/

2. Date table properties


•All dates should be present –no gaps
•From 1°of January, to 31°of December
•Or for the fiscal calendar including full months
•Otherwise time intelligence DAX functions do not work
GrowTechie

Auto date/time and column variations


In Power BI the auto date/time setting automatically creates one date table for each date
column in the model.
It is not a best practice, unless you are using a very simple model. Columns in these auto-
created tables can be accessed through “column variations”.
GrowTechie

CALENDARAUTO
Automatically creates a calendar table based on the database content.

Optionally you can specify the last month (for fiscal years).
GrowTechie

CALENDAR
Returns a table with a single column named “Date” containing a contiguous set of dates in
the given range, inclusive.

CALENDAR (DATE ( 2005, 1, 1 ),


DATE ( 2015, 12, 31 )
)

CALENDAR (
MIN ( Sales[Order Date] ),
MAX ( Sales[Order Date] )
)
GrowTechie

Mark as date table


1. Need to mark the calendar as date table

2.Set the column containing the date

3.Needed to make time intelligence work if the relationship does not use a Date column

4. Multiple tables can be marked as date table

5.Used by client tools as metadata information


GrowTechie

Set sorting options


O Month names do not sort alphabetically
•April is not the first month of the year

O Use Sort By Column

O Set all sorting options in the proper way

O Beware of sorting granularity


•1:1 between names and sort keys
GrowTechie

Using multiple dates


O Date is often a role dimension
•Many roles for a date
•Many date tables

O How many date tables?


•Try to use only one table
•Use many, only if needed by the model
•Many date tables lead to confusion
•And issues when slicing

O Use proper naming convention


GrowTechie

Time intelligence functions

Time intelligence in DAX


GrowTechie

What is time intelligence?

1. Many different topics in one name


•Year To Date
•Quarter To Date
•Running Total
•Same period previous year
•Working days computation
•Fiscal Year
GrowTechie

Aggregations over time

O Many useful aggregations


•YTD: Year To Date
•QTD: Quarter To Date
•MTD: Month To Date

O They all need a date table

O And some understanding of CALCULATE


GrowTechie

Sales 2015 up to 05-15 (v1)


Using CALCULATE you can filter the dates of the period to summarize.

SalesAmount20150515 :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
ALL ( 'Date'[Date] ),
AND ('Date'[Date] >= DATE ( 2015, 1, 1 ),
'Date'[Date] <= DATE ( 2015, 5, 15 )
)
)
)
GrowTechie

Sales 2015 up to 05-15 (v2)


You can replace FILTER with DATESBETWEEN.
The result is always a table with a column.

SalesAmount20150515 :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
DATESBETWEEN (
'Date'[Date],
DATE ( 2015, 1, 1 ),DATE ( 2015, 5, 15 )
)
)
GrowTechie

Sales Year-To-Date (v1)


Replace the static dates using DAX expressions that retrieve the last day in the current filter.

SalesAmountYTD:=
CALCULATE (
SUM ( Sales[SalesAmount] ),
DATESBETWEEN (
'Date'[Date],
DATE ( YEAR ( MAX ( 'Date'[Date] ) ), 1, 1 ),MAX (
'Date'[Date] )
)
)
GrowTechie

Year to date (Time Intelligence)


Replace the static dates using DAX expressions that retrieve the last day in the current filter.

SalesAmountYTD:=
CALCULATE (
SUM ( Sales[SalesAmount] ),
DATESBETWEEN (
'Date'[Date],
DATE ( YEAR ( MAX ( 'Date'[Date] ) ), 1, 1 ),MAX (
'Date'[Date] )
)
)
GrowTechie

Year to date: the easy way

TOTALYTD: the “DAX for dummies” version.


It hides the presence of CALCULATE, so we suggest not to use it.

SalesAmountYTD :=

TOTALYTD (
SUM ( Sales[SalesAmount] ),
'Date'[Date]
)
GrowTechie

Handling fiscal year


The last, optional, parameter is the end of the fiscal year.
Default: 12-31 (or 31/12 –you can use any format regardless of locale
settings).

SalesAmountYTD:=

TOTALYTD (SUM ( Sales[SalesAmount] ),'Date'[Date],"06-


30")

SalesAmountYTD:=

CALCULATE (SUM ( Sales[SalesAmount] ),DATESYTD (


'Date'[Date], "06-30" ))
GrowTechie

Thank you

Follow me and Growtechie

@Ramakrushnamohapatra
@growtechieind

You might also like