DAX Zero To Developer
DAX Zero To Developer
ZERO TO DEVELOPER
by Tajamul Khan
PREREQUISITES DAX Comments TIME INTELLIGENCE
Data vs Lookup tables Error Handling Data Table
Primary vs Foreign Key Variables Calendar
Cardinality SCALAR FUNCTIONS Performance Till Date
Filter Flow Aggregate Functions Time Period Shift
CONTENTS
Iterator Functions Running Total Functions
DAX
Introduction Round Functions PERFORMANCE TUNING
LOOKUP TABLES
provide descriptive attributes about each dimension in your model (customers, products)
1
Data Blogs Follow Tajamul Khan
FOREIGN KEY
they contain multiple instances of each value, and are used to match the primary keys
in related lookup tables
2
Data Blogs Follow Tajamul Khan
CARDINALITY
refers to the uniqueness of values in a column. It can be of many types
One to Many
Many to One
Many to Many
One to One
For our purposes, all relationships in the data model should follow a “one to many”
cardinality; one instance of each primary key to many instances of each foreign key
FILTER FLOW
Filter Flow always runs “ downstream ” from Lookup to Data Table
Filters cannot flow “ upstream ” (against the direction)
3
DAX
Data Blogs Follow Tajamul Khan
DAX
DAX also known as Data Analysis Expressions is a functional
language i.e. the execution flows with function calls, It is used in
Power BI
Analysis Services Tabular
Power Pivot
It resembles excel because it was born with PowerPivot
FORMATTING
Code formatting is of paramount importance in DAX.
4
Data Blogs Follow Tajamul Khan
DAX ENGINES
DAX is powered by two internal engines (formula engine & storage engine) which
work together to compress & encode raw data and evaluate DAX queries
FORMULA ENGINE
Receives, interprets and executes all DAX requests
Processes the DAX query then generates a list of logical steps called a query plan
Works with the datacache sent back from the storage engine to evaluate the DAX
query and return a result
STORAGE ENGINE
Compresses and encodes raw data, and only communicates with the formula engine
(doesn’t understand the DAX language)
Receives a query plan from Formula Engine, executes it, and returns a datacache
5
Data Blogs Follow Tajamul Khan
DAX Query
Formula
Storage
Engine
Engine
Output
Data
Cache
6
Data Blogs Follow Tajamul Khan
DATA TYPES
Integer (64 bit) Whole Number
DAX TYPE HANDLING
Decimal (Floating Point) OPERATOR OVERLOADING
Currency (Fixed Decimal Number) Operators are not strongly typed
The result depends on the inputs
Date, DateTime, Time example:
TRUE / FALSE (Boolean) "4" + "8" = 12
String (Unicode String) 4 & 8 = "48"
Data types represent how values are stored by the DAX storage engine
7
Data Blogs Follow Tajamul Khan
DAX OPERATORS
8
Data Blogs Follow Tajamul Khan
VERTIPAQ
VertiPaq uses a columnar data structure , which stores data as individual columns
(rather than rows or full tables) to quickly and efficiently evaluate DAX queries
ID PRODUCT AMOUNT ID PRODUCT AMOUNT
1 Oats 20 1 Oats 20
2 Biscuit 40 2 Biscuit 40
3 Milk 100 3 Milk 100
9
Data Blogs Follow Tajamul Khan
CALCULATED COLUMNS
Allow you to add new, formula based columns to tables
Values are calculated based on information from each row of a table (has row
context)
Appends static values to each row in a table and stores them in the model ( which
increases file size).
Recalculate on data source refresh or when changes are made to component
columns
Primarily used as slicers or filters
10
Data Blogs Follow Tajamul Khan
MEASURES
Values are calculated based on information from any filters in the report (has
filter context
Does not create new data in the tables themselves
Recalculate in response to any change to filters within the report
Almost always used within the values field of a visual
12
Data Blogs Follow Tajamul Khan
EVALUATION CONTEXT
Evaluation contexts are the pillars of DAX i.e., Filter and Row
Row Context : Iterates rows
Filter Context : Filters tables
Functions like RELATED() or EARLIER() work with Functions like CALCULATE() and FILTER() use Filter
Example
Row Context. Context.
Key Use Applied to calculated columns in DAX. Applied to measures and aggregation in DAX.
13
Data Blogs Follow Tajamul Khan
FILTER CONTEXT
Filter context filters the tables in your data model
DAX creates filter context when dimensions are added to rows , columns , slicers & filters
CALCULATE can be used to systematically create or modify existing filter context
Filter context always travels (propagates) from the ONE side to the MANY side of a
table relationship
ID COUNTRY AMOUNT
1 India 20
India 2 India 40
3 US 100
Total 60
14
Data Blogs Follow Tajamul Khan
ROW CONTEXT
Row context iterates through the rows in a table
DAX creates row context when you add calculated columns to your data model
Iterator functions (SUMX, RANKX, etc.) use row context to evaluate row level
calculations
Row context doesn't automatically propagate through table relationships (need
to use RELATED or RELATEDTABLE functions)
15
GOOD PRACTICES
Data Blogs Follow Tajamul Khan
NAMING CONVENTIONS
Measures should not belong to a table
• Avoid table name
• [Margin%] instead of Sales[Margin%]
• Should be Easier to move to another table
• Should be Easier to identify as a measure
Columns → Table[Column]
Measures → [Measure]
16
Data Blogs Follow Tajamul Khan
EVALUATION ORDER
is the process by which DAX evaluates the parameters in a function
NON NESTED
IF( Test, True, False )
1 2 3
NON NESTED
SUMX
FILTER(
FILTER ( ‘Table’ 1 = Inner Most Filter
RELATED ( ‘Table’[Column], 2
RELATED( ‘Table’[Column]), 3 = Outer
‘Table’[Column]),
17
Data Blogs Follow Tajamul Khan
DAX SHORTCUTS
ACTION KEYBOARD SHORTCUT
Go to Line Control + G
18
Data Blogs Follow Tajamul Khan
Bad comment
Total Sales = SUM(Sales[SalesAmount]) --Sum the sales amount
Good comment
Total Sales = SUM(Sales[SalesAmount]) --Calculate total sales amount
19
Data Blogs Follow Tajamul Khan
ERROR HANDLING
Error handling functions can be used to help identify missing data, and can be
particularly useful for quality assurance and testing
IFERROR()
Returns a value if first expression is an error and the
value of the expression itself otherwise
IFERROR(DIVIDE([Numerator], [Denominator]), 0)
ISBLANK()
Checks to see if a value is blank, returns True or False
IF(ISBLANK([Sales]), 0, [Sales])
20
Data Blogs Follow Tajamul Khan
VARIABLES
Very useful to avoid repeating subexpressions in your DAX code.
Variables can be a helpful tool for testing or debugging your DAX code
21
SCALAR FUNCTIONS
Data Blogs Follow Tajamul Khan
AGGREGATE INFORMATION
ROUND LOGICAL
22
Data Blogs Follow Tajamul Khan
AGGREGATE FUNCTIONS
Functions that can be used to dynamically aggregate values within a column
23
Data Blogs Follow Tajamul Khan
ITERATOR FUNCTIONS
Iterate over the table and evaluate the expression for each row
ROUND FUNCTIONS
Functions that can be used to round values to different levels of precision
25
Data Blogs Follow Tajamul Khan
INFORMATION FUNCTIONS
Functions that can be used to analyze the data type or output of an expression
26
Data Blogs Follow Tajamul Khan
LOGICAL FUNCTIONS
Functions for returning information about values in a conditional expression
27
CALCULATE
Data Blogs Follow Tajamul Khan
CALCULATE
It is one of the most powerful and versatile functions. It allows you to modify the
existing filter context of a calculation, enabling you to perform complex
calculations and aggregations.
28
Data Blogs Follow Tajamul Khan
CONTEXT TRANSITION
Context Transition is the process of turning row context into filter context
By default, calculated columns understand row context but not filter context
To create filter context at the row-level, you can use CALCULATE
29
Data Blogs Follow Tajamul Khan
EVALUATION ORDER
CALCULATE(
3[Quantity],
2 Table[ID] = 4
1 ALL(Table) # All Modifier is evaluated first
MODIFIERS
Modifiers are used to alter the way CALCULATE creates filter context, and are
added as filter arguments within a CALCULATE function
ALL
ALLSELECTED
ALLEXCEPT
KEEPFILTERS
Calculate Modifiers Only
REMOVEFILTERS
30
TABLE FUNCTIONS
Data Blogs Follow Tajamul Khan
31
Data Blogs Follow Tajamul Khan
ALL FUNCTION
Returns all the rows in a table, or all the values in a column, ignoring any filters
ALL is both a table filter and a CALCULATE modifier
Removes initial filter context IGNORES
Does not accept table expressions FILTERS
(only physical table references)
Returns Table
CALCULATE(SUM(Sales[Amount]), ALL(Sales))
32
Data Blogs Follow Tajamul Khan
FILTER FUNCTION
Returns a filtered table, based on one or more filter expressions
FILTER is both a table function and an iterator
FILTER TABLE
Often used to reduce the number of rows to scan
Returns Table
CALCULATE(SUM(Sales[Amount]),
FILTER(Sales, Sales[Amount] > 1000))
33
Data Blogs Follow Tajamul Khan
DISTINCT
NumOfProducts =
Returns the unique values of a column COUNTROWS ( DISTINCT(
only the ones visible in the current filter context. Product[ProductCode]))
VALUES
Returns the unique values of a column, NumOfProducts =
only the ones visible in the current filter context, COUNTROWS ( VALUES(
including the additional blank row if it is visible Product[ProductCode]))
in the filter context.
Use DISTINCT to create new dimension table by extracting unique values from fields
in data table!
34
Data Blogs Follow Tajamul Khan
VALUES will always consider the blank rows but DISTINCT will not
35
Data Blogs Follow Tajamul Khan
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" )
36
Data Blogs Follow Tajamul Khan
ALL SELECTED
ALLSELECTED() returns all rows in a table or values in a column, ignoring inner filters
i.e., specified in the visual but respecting other existing filter context.
37
Data Blogs Follow Tajamul Khan
ALL EXCEPT
The ALLEXCEPT function in DAX is used to remove all context filters in a table except
for the filters specified in the function arguments.
38
Data Blogs Follow Tajamul Khan
39
Data Blogs Follow Tajamul Khan
40
TABLE JOINS
Data Blogs Follow Tajamul Khan
41
RELATION FUNCTIONS
Data Blogs Follow Tajamul Khan
TERMINOLOGY
PHYSICAL TABLE VS VIRTUAL TABLE
Physical relationships are manually created, and visible in your data model
Virtual relationships are temporary, and defined using DAX expressions
42
Data Blogs Follow Tajamul Khan
RELATIONSHIP FUNCTIONS
43
TIME INTELLIGENCE
Data Blogs Follow Tajamul Khan
DATE TABLE
Date Table is very important for Time Intelligence
44
Data Blogs Follow Tajamul Khan
45
Data Blogs Follow Tajamul Khan
CALENDAR
Returns a table with one column of all dates between start and end date
CALENDAR(StartDate, EndDate)
46
Data Blogs Follow Tajamul Khan
CALENDARAUTO()
Returns a table with one column of dates based on a fiscal year end month. The
Range of dates is calculated automatically based on data in the model.
Calendarauto(6) means it starts from 01/07
CALENDARAUTO(FiscalYearEndMonth)
47
Data Blogs Follow Tajamul Khan
DATE FORMATTING
Used to specify date/time formatting. Common examples include:
48
Data Blogs Follow Tajamul Khan
49
Data Blogs Follow Tajamul Khan
50
Data Blogs Follow Tajamul Khan
51
Data Blogs Follow Tajamul Khan
52
PERFORMANCE TUNING
Data Blogs Follow Tajamul Khan
PERFORMANCE ANALYZER
Power BI’s Performance Analyzer can help us troubleshoot issues, measure load
times for visuals/DAX queries, and optimize your code
Power BI Desktop’s Performance Analyzer records user actions (like Excel’s macro
recorder), and tracks the load time (in milliseconds) for each step in the process:
53
Data Blogs Follow Tajamul Khan
DAX STUDIO
DAX Studio is a free tool that allows you to connect to your Power BI data model to test and
optimize your DAX queries
54
CHEAT SHEET
Data Blogs Follow Tajamul Khan
55
Data Blogs Follow Tajamul Khan
56
Data Blogs Follow Tajamul Khan
Logical Distribution
IF: IF( 'Table'[Column] > NORM. DIST: NORM. DIST
10, "Yes", "No")| (1.96, 0, 1, TRUE)
AND: AND('Table'[Column1] > NORM. INV: NORM. INV (0.95,
5, 'Table'[Column2] < 10) 0, 1)
OR: OR('Table' [Column1] > BINON. DIST: BINOM. DIST(3,
5, 'Table' [Column2] < 10) 10, 0.5, FALSE)
NOT: NOT( 'Table' [Flag]) | POISSON. DIST: POISSON.
SWITCH: SWITCH('Table' DIST(2, 5, FALSE)
[Category],"A",1,"B",2,0)
57
Data Blogs Follow Tajamul Khan
Finance Ranking
PV: PV(0.05, 10, 1000, 0, 0) RANKX: RANKX('Table',
FV: FV(0.05, 10, -100, 0, 0) 'Table' [Sales], , DESC)
MPV: NPV(0.1, CashFlow1, TOPN: TOPN(5, 'Table',
CashFlow2, CashFlow3) 'Table'[Sales], DESC)
IRR: IRR(CashFlows) RANK.EQ: RANK.EQ( 'Table'
TOTALYTD: TOTALYTD(SUM( 'Table' [Sales], 'Table' [Sales],
[Revenue]), 'Date' [Date]) DESC)
CLOSINGBALANCEMONTH:
CLOSINGBALANCEMONTH ( 'Table'
[Revenue],'Date' [Date])
OPENINGBALANCEMONTH:
OPENINGBALANCEMONTH (' Table'
[Revenue],'Date'[Date])
58
Data Blogs Follow Tajamul Khan
Testing Ranking
T.TEST: T. TEST('Group' [Data], TOTALYTD: TOTALYTD(SUM ('Table' [Sales]),
'Group2' [Data], 2, 1) 'Date'[Date])
SAMEPERIODLASTYEAR: CALCULATE(SUM('Table'
ANOVA: ANOVA( 'Table' [Values],
[Sales]).
'Table' [Category]) SAMEPERIODLASTYEAR ('Date' [Date]) )
CHISQ. DIST: CHISQ. DIST (3.84, YTD: CALCULATE (SUM('Table' [Sales]),
2, FALSE) ALL('Date'), 'Date' [Date] <= MAX ( 'Date'
PERCENTILE.INC: PERCENTILE. INC( [Date]) )
QUARTER: QUARTER('Date' [Date])
'Table' [Values], 0.75)
MONTH: MONTH 'Date' [Date])
PERCENTILE.EXC: PERCENTILE. WEEKDAY: WEEKDAY ('Date' [Date], 2)
EXC('Table' [Values], 0.75) CALENDAR: CALENDAR (DATE (2023, 1, 1),
RANK. AVG: RANK. AVG( 'Table' DATE(2023, 12, 31))
[Sales], 'Table' [Category], 1) DATESBETWEEN: DATESBETWEEN( 'Date' [Date],
DATE(2022, 1, 1), DATE (2022, 12, 31))
KEEPFILTERS:
TOTALMTD: TOTALMTD(SUM( 'Table' [Sales]),
KEEPFILTERS(CALCULATE (SUM( 'Date' [Date])
'Table' [Sales]), 'Table' FIRSTDATE: FIRSTDATE ('Date' [Date])
[Category] = "A")) LASTDATE: LASTDATE (('Date' [Date])
59
Data Blogs Follow Tajamul Khan
Table Parent-Child
VALUES: VALUES('Table'[Column ]) PATH: PATH('Table', 'Table'
ALLSELECTED: ALLSELECTED('Table') [ParentID], 'Table' [ID])
ADDCOLUMNS: ADDCOLUMNS ('Table',
PATHITEM: PATHITEM('Table'
"Revenue", 'Table' [Quantity] * 'Table'
[Price]) [Path], 1)
SUMMARIZE: SUMMARIZE ('Table', 'Table' PATHLENGTH: PATHLENGTH('Table'
[Category], "Total Sales", SUM( 'Table' [Path])
[Sales]))
ISFILTERED: IF(ISFILTERED
ROLLUP: ROLLUP('Date', 'Date' [Year],
'Date' [Quarter], 'Date' [Month])
('Table' [Column]), "Filtered",
KEEPFILTERS: KEEPFILTERS "Not Filtered")
(CALCULATETABLE('Table', 'Table'
[Column] > 100))
SELECTCOLUMNS: SELECTCOLUMNS( 'Table',
'Table' [Column1], 'Table' [Column2])
SUMMARIZECOLUMNS: SUMMARIZECOLUMNS(
'Table' [Column1], 'Table' [Column2],
"Total Sales", SUM(‘Table’[Sales]))
60
Data Blogs Follow Tajamul Khan
Advanced Information
PREDICT: PREDICT('Table', 'Table' ISBLANK: IF (ISBLANK
[Value], FILTER('Table', 'Table'
('Table' [Column]), "Blank",
[Date] > DATE(2022, 1, 1)))
COVARIANCE.P: COVARIANCE.P(
"Not Blank")
'Table1' [Values], 'Table2' ISERROR: IF(ISERROR(1/0),
[Values]) "Error", "No Error")
CORRELATION: CORRELATION( TYPEOF: TYPEOF ( 'Table'
'Table1'[Values], 'Table2'[Values])
[Column], INTEGER)
RANK.EQ: RANK.EQ( 'Table' [Sales],
'Table' [Sales], DESC,'Table'
[Category])
PREDICT: PREDICT('Table', 'Table'
[Value], FILTER('Table','Table'
[Date] > DATE(2022, 1, 1)))
COVARIANCE.P: COVARIANCE.P('Table1'
[Values], 'Table2' [Values])
61
Data Blogs Follow Tajamul Khan
Parameter Context
ISBLANK: IF (ISBLANK ('Table' EARLIER: CALCULATE (SUM(
[Column]), "Blank", "Not 'Table' [Sales]), 'Table'
Blank") [Date] = EARLIER ('Table'
ISERROR: IF(ISERROR(1/0), (Date]) - 1)
"Error", "No Error") FILTERS: FILTERS( 'Table'
TYPEOF: TYPEOF ( 'Table' [Category])
[Column], INTEGER) USERELATIONSHIP:
USERELATIONSHIP(' Table1'
[Column], 'Table2'
[Column])
62
FREE
DATA
RESOURCES
FREE PROJECTS
FREE FREE FREE
MACHINE EDA STATISTICS
LEARNING PROJECTS PROJECTS
PROJECTS