www.sqlbi.
com
Who We Are
o   BI Experts and Consultants
o   Founders of www.sqlbi.com
    •   Problem Solving
    •   Complex Project Assistance
    •   Data Warehouse Assessments and Development
    •   Courses, Trainings and Workshops
o   Book Writers
o   Microsoft Gold Business Intelligence Partners
o   SSAS Maestros – MVP – MCP
The DAX Language
o   Language of
    • Power Pivot
    • Power BI
    • SSAS Tabular
o   DAX is simple, but it is not easy
o   New programming concepts and patterns
Introduction to the DAX language
Introduction to DAX
What is DAX?
o Programming language
   • Power Pivot
   • SSAS Tabular
   • Power BI
o Resembles Excel
   • Because it was born with PowerPivot, in 2010
o Important differences
   • No concept of «row» and «column»
   • Different type system
o Many new functions
o   Designed for data models and business calculations
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
   )
)
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,[S
ales Amount]*100,[Sales Amount]*90)
=SUMX (
   FILTER (
       VALUES ( 'Date'[Year] ),
        'Date'[Year] < 2005
   ),
   IF (
       'Date'[Year] >= 2000,
       [Sales Amount] * 100,
       [Sales Amount] * 90
)                                     www.daxformatter.com
Calculated Columns
o   Columns computed using DAX
o   Always computed for the current row
o   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
Measures
o   Written using DAX
o   Do not work row by row
o   Instead, use tables and aggregators
o   Do not have the «current row» concept
o   Examples
    • GrossMargin
      • is a calculated column
      • but can be a measure too
    • GrossMargin %
      • needs to be a measure
Naming Convention
o   Measures do 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
o   Thus
    • Calculated columns  Table[Column]
    • Measures  [Measure]
Measures vs Calculated Columns
o   Use a column when
    • Need to slice or filter on the value
o   Use a measure
    • Calculate percentages
    • Calculate ratios
    • Need complex aggregations
o   Space and CPU usage
    • Columns consume memory
    • Measures consume CPU
Aggregation Functions
o   Useful to aggregate values
    •   SUM
    •   AVERAGE
    •   MIN
    •   MAX
o   Work only on numeric columns
o   Aggregate only one column
    • SUM ( Orders[Price] )
    • SUM ( Orders[Price] * Orders[Quantity] )
The «X» Aggregation Functions
o   Iterators: useful to aggregate formulas
    •   SUMX
    •   AVERAGEX
    •   MINX
    •   MAXX
o   Iterate over the table and evaluate the expression for
    each row
o   Always receive two parameters
    • Table to iterate
    • Formula to evaluate for each row
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»
SUMX (
    Sales,
    Sales[Price] * Sales[Quantity]
)
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
      )
Date Functions
o   Many useful functions
    •   DATE, DATEVALUE, DAY, EDATE,
    •   EOMONTH, HOUR, MINUTE,
    •   MONTH, NOW, SECOND, TIME,
    •   TIMEVALUE, TODAY, WEEKDAY,
    •   WEEKNUM, YEAR, YEARFRAC
o   Time Intelligence functions will be covered later
Some functions return tables instead of values
Table Functions
Table Functions
o   Basic functions that work on full tables
    •   FILTER
    •   ALL
    •   VALUES
    •   DISTINCT
    •   RELATEDTABLE
o   Their result is often used in other functions
o   They can be combined together to form complex
    expressions
o   We will discover many other table functions later in the
    course
CALCULATED TABLES
o   In the newest versions of Tabular (and in Power BI
    Desktop), you can create calculated tables
o   User interface is different in different products
Filtering a Table
                    SUMX (
                      FILTER (
                         Orders,
                         Orders[Price] > 1
                      ),
                      Orders[Quantity] * Orders[Price]
                    )
The FILTER Function
o   FILTER
    •   Adds a new condition
    •   Restricts the number of rows of a table
    •   Returns a table
    •   Can be iterated by an «X» function
o   Needs a table as input
o   The input can be another FILTER
Removing Filters
                   SUMX (
                     ALL ( Orders ),
                     Orders[Quantity] * Orders[Price]
                   )
The ALL Function
o   ALL
    •   Returns all the rows of a table
    •   Ignores the filter context
    •   Returns a table
    •   That can be iterated by an «X» function
o   Needs a table as input
o   Can be used with a single column
    • ALL ( Customers[CustomerName] )
    • The result contains a table with one column
Mixing Filters
o   Table functions can be mixed
o   Each one requires a table
o   Each one returns a table
o   FILTER ( ALL ( Table ), Condition )
    • Puts a filter over the entire table
    • Ignores the current filter context
Mixing Filters
                 SUMX (
                   FILTER (
                      ALL( Orders ),
                      Orders[Channel]="Internet"
                   ),
                   Orders[Quantity] * Orders[Price]
                 )
DISTINCT
Returns the distinct values of a column, only the ones visible in the current context
 NumOfProducts :=
 COUNTROWS (
     DISTINCT ( Product[ProductCode] )
 )
RELATEDTABLE
Returns a table with all the rows related with the current one.
NumOfProducts =
COUNTROWS (
    RELATEDTABLE ( Product )
)
Example of RELATEDTABLE
Compute the number of red products for a category. Build a calculated column in the
Categories table:
NumOfRedProducts =
COUNTROWS (
    FILTER (
        RELATEDTABLE ( Product ),
        Product[Color] = "Red"
    )
)
Let us take a look at how DAX works
Evaluation Contexts
What is an Evaluation Context?
TotalSales := SUM ( Sales[SalesAmount] )
                                           Numbers are sliced by color, i.e.
                                           the formula is NOT computing
                                           sum of sales, it is computing it
                                           for only a subset of the data
                                           model
                         The value of a formula
                         depends on its context
Sources of the Context
      PivotTable Filter                    Columns
                                    Rows
                          Slicers
Example of a Filter Context
Filter Context
o   Defined by
    •   Row Selection
    •   Column Selection
    •   Report Filters
    •   Slicers Selection
o   Rows outside of the filter context
    • Are not considered for the computation
o   Defined automatically by PivotTable, can be created
    with specific functions too
Row Context
o   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
o   Needed to evaluate column values, it is the concept of
    “current row”
SUMX ( Orders, [Quantity]*[Price] )
                                       SUM = 592
                            16x7=112
                            32x5=160
                            64x3=192
                           128x1=128
There Are Always Two Contexts
o   Filter context
    • Filters tables
    • Might be empty
      • All the tables are visible
      • But this never happens in the real world
o   Row context
    • Iterates rows
    • For the rows active in the filter context
    • Might be empty
      • There is no iteration running
o   Both are «evaluation contexts»
Filtering a Table
                    SUMX (
                      FILTER (
                         Orders,
                         Orders[Price] > 1
                      ),
                      Orders[Quantity] * Orders[Price]
                    )
Removing Filters
                   SUMX (
                     ALL ( Orders ),
                     Orders[Quantity] * Orders[Price]
                   )
The queen of all DAX functions 
CALCULATE
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
CALCULATE (
    Expression,
    Filter1,
    …                 Repeated many times, as needed
    Filtern
)
CALCULATE Examples
Compute the sum of sales where the price is more than $100.00
 NumOfBigSales :=
 CALCULATE (
     SUM ( Sales[SalesAmount] ),
     Sales[SalesAmount] > 100
 )
                                           Filter and SUM are
                                           on the same table.
                                         You can obtain the same
                                            result using FILTER
Filters are tables
Each filter is a table. Boolean expressions are nothing but shortcuts for table expressions
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    Sales[SalesAmount] > 100
)
Is equivalent to
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    FILTER (
        ALL ( Sales[SalesAmount] ),
        Sales[SalesAmount] > 100
    )
)
Clear filter on one column only
       CALCULATE (
           SUMX (
               Orders,
                                     ALL used with a
               Orders[Amount]         single column
           ),                              table
           ALL ( Orders[Channel] )
       )
CALCULATE Tasks
o   Partially replaces the filter context
o   Conditions
    • Can replace a whole table
    • Can replace a single column
o   CALCULATE works on the filter context
Evaluation Contexts
And Relationships
Filters and Relationships
o   Do contexts interact with
    relationships?
o   Row Context
o   Filter Context
o   One side
o   Many side
Row Context – Many Tables
o   Row Context
    • Does not propagate over relationships
RELATED
o   RELATED ( table[column] )
    • Opens a new row context on the target table
    • Following relationships
RELATEDTABLE
o   RELATEDTABLE ( table )
    • Filters the parameter table
    • Returns only rows related with the current one
o   It is the companion of RELATED
Filter Context – Many Tables
o   Filter Context and Relationships
    • Relationships affect filter context
o   Orders  Products
    • Filter context on Orders
    • Follows the relationship
    • Shows only products of the selected orders
o   Different from Row Context
Filter Context – Many Tables
Filter Context – Many Tables
Filters and Relationships
        Filter context propagates
         following the available
     directions of each relationship
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…
Automatic CALCULATE
Whenever a measure is computed, an automatic CALCULATE is added around the measure
SUMX (
    Orders,
    [Sales Amount]
)
SUMX (
    Orders,
    CALCULATE ( [Sales Amount] )
)
Time intelligence functions
Time Intelligence in DAX
Date Table
o   Time intelligence needs a date table
    • Built in DAX
    • Or in a SQL Table
o   Date table properties
    •   All dates should be present
    •   From 1° of January, to 31° of December
    •   No holes
    •   Otherwise time intelligence will not work
CALENDAR                                                                                    2015
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] )
 )
CALENDARAUTO                                                                               2015
Automatically creates a calendar table based on the database content. Optionally you can
specify the last month (useful for fiscal years)
 --
 -- The parameter is the last month
 -- of the fiscal year
 --
 = CALENDARAUTO (
     6
 )                      Beware: CALENDARAUTO                uses
                                   all the dates in your model,
                                    excluding only calculated
                                        columns and tables
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
What is Time Intelligence?
o   Many different topics in one name
    •   Year To Date
    •   Quarter To Date
    •   Running Total
    •   Same period previous year
    •   Working days computation
    •   Fiscal Year
o   In short: anything related with time
    • Handled in an intelligent way
Aggregations Over Time
o   Many useful aggregations
    • YTD: Year To Date
    • QTD: Quarter To Date
    • MTD: Month To Date
o   They all need a Calendar Table
o   And some understanding of CALCULATE
Year To Date (Time Intelligence)
DATESYTD makes filtering much easier
SalesAmountYTD :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    DATESYTD ( 'Date'[Date] )
)
Handling Fiscal Year
The last, optional, parameter is the end of the fiscal year
Default: 12-31 (or 31/12 - locale dependent)
SalesAmountYTD :=
TOTALYTD (
    SUM ( Sales[SalesAmount] ),
    'Date'[Date],
    "06-30"
)
SalesAmountYTD :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    DATESYTD ( 'Date'[Date], "06-30" )
)
Same Period Last Year
Same period in previous year. CALCULATE is needed
Specialized version of DATEADD
Sales_SPLY :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    SAMEPERIODLASTYEAR ( 'Date'[Date] )
)
Running Total
Running total requires an explicit filter
SalesAmountRT :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    FILTER (
        ALL ( 'Date' ),
       'Date'[Date] <= MAX ( 'Date'[Date] )
    )
)
Thank you!
Check our articles, whitepapers and courses on
           www.sqlbi.com