The Power of DAX

## What is DAX?

*Data Analysis Expressions (DAX)* is a library composed of over 200 functions, operators, and constants that can be used in formulas, and/or expressions, to calculate and return one or more values. DAX helps with creating new information from the data already present in the model.

## Why use DAX?

* It provides flexibility in creating measures to calculate results for just about any data analysis which allows for DAX to aid in solving business problems.
* It uses standard functionality to formulas that are also used in Power Pivot in Excel.
	+ (SUM, SUMIF, VLOOKUP, etc.)

## Writing DAX Formulas

* A *DAX formula* consists of expressions that return a result (either a table object or a scalar value).

* Each model calculation type, calculation table, calculated column, or measure is defined by its name, followed by the equals symbol (=), which is then followed by a DAX formula.
	+ Example:
	```
	<Calculation name> = <DAX formula>
	```
* Referencing a table:
	+ The table name should be enclosed within single quotation marks (**'**Table Name**'**).
		- Example:
		```
		<Calculation name> = 'Table name'
		```
* Referencing a column:
	+ The column name should be enclosed within square brackets (**[**Column Name**]**).
		- Tip: To improve the readability of a formula, precede column reference with its table name.
		- Example:
		```
		<Calculation name> = SUM('Table name'[Column name])
		```
* Referencing a measure:
	+ The measure should be enclosed within square brackets (**[**Measure Name**]**).
		- Example:
		```
		<Calculation name> = [Measure] - [Measure]
		```
* Variables:
	+ Variables can be defined in an expression to make DAX easier.
	+ This is very similar to having variables in a coding language (such as Python) that you can reference.
	+ Benefits of variables:
		- Improves the readability of a formula
		- Improves the performance when an expression is used multiple times
		- Allows for testing of portions of more complex functions by returning only a variable for review
	+ Example:
	```
	<Calculation name> =
	    VAR <Variable name1> =
	        <DAX formula>
	    VAR <Variable name2> =
	        <DAX formula>
	    RETURN
	        DIVIDE(
	            <Variable name1>,
	            <Variable name2>
	        )
	```
* Whitespace:
	+ This refers to the characters (spaces, tables, carriage returns) that format formulas in a way that is quick and simple to understand.
	+ Usage:
		- Spaces between operators
		- Tabs to indent nested function calls
		- Carriage returns to separate function arguments
	+ More whitespace the better!
	+ Example:
	```
	--NOT formatted with whitespace--
	<Calculation name> = DIVIDE([<Measure>] - CALCULATE([<Measure>], SAMEPERIODLASTYEAR('Table name'[column name])), CALCULATE([<Measure>], SAMEPERIODLASTYEAR('Table name'[column name])))

	--FORMATTED with whitespace--
	<Calculation name> =
	DIVIDE(
	    [<Measure>]
	        - CALCULATE(
	            [<Measure>],
	                SAMEPERIODLASTYEAR ('Table name'[column name])
	    ),
	    CALCULATE(
	        [<Measure>],
	        SAMEPERIODLASTYEAR('Table name'[column name])
	    )
	)
	```

## Define Calculated Tables and Calculated Columns

*Calculated table*:

* A calculated table adds a new table to the model using a DAX formula.
	+ A calculated table can duplicate or transform an existed table, but it must return a table object.
	+ A calculated table cannot connect to external data, if you want to achieve this then Power Query can be used
* Disadvantages of calculated tables:
	+ Increases the storage size of the model
	+ Can prolong the data refresh time
	+ Cannot connect to external data (Power Query can be used if this is what you want to achieve)

* Difference between a table and calculated table at a quick glance: (click on picture to see an enlarged picture)

*Calculated column:*

* A calculated column adds a new column to a table within the model using a DAX formula.
	+ A calculated column must return a scalar (single) value.
	+ A calculated column performs an evaluation for each of the table's row.
* Disadvantages of calculated columns:
	+ Increases the storage size of the model
	+ Can prolong the data refresh time
* Difference between a column and calculated column at a quick glance: (click on picture to see an enlarged picture)
* Choosing a technique to add a column:
	+ 3 techniques to add a column to a table:
		- Add a column in the data source
		- Add a computed column to a query in Power Query (using M)
		- Add a calculated column to a model table (using DAX)
	+ How to choose which technique to use?
		- Use the approach that best fits your skills and is supported by the language (either M or DAX)
			* However, it is more preferable to add computed columns in Power Query because these will load to the model in a more compact way.

## Define Measures

*Measures*

* A measure summarizes the model data.
	+ The formula must return a scalar (single) value.
	+ The results are never stored in the model.
	+ Some people prefer to create and use a measure table to store all their measures for the model.
* How to create a measure:
	+ In the ribbon located at the top of the page when in the Data view: Home > Calculations > New Measure
* Quick measures
	+ Power BI Desktop supports quick measures
	+ Benefits:
		- quick and easy
		- common calculation templates are available
		- automatically creates the DAX expression
* How to create a quick measure:
	+ In the ribbon located at the top of the page when in the Data view: Home > Calculations > Quick Measure
* 2 types of measures:
	+ Implicit measure
		- An implicit measure is a model column that is summarized.
		- Appears with the sigma symbol in the Fields pane
		- Always numeric columns (remember algebra must make sense!)
		- Benefits:
			* simple to use
			* easy to learn
			* less work as a data modeler
		- Limitations:
			* easy to choose wrong default
			* limited scenarios
	+ Explicit measure
		- An explicit measure is a measure defined using DAX.
		- Defines a formula that returns a scalar (single) value
		- Does not store values in the model
		- Limitations:
			* cannot reference tables and/or columns directly

## Iterator ("X") Functions

Iterator functions are a part of the Math & Stats functions within DAX and you can think of them as a sum product on steroids. They allow you to loop through the same calculation or expression on every single row of a table and then apply some sort of aggregation to the results.

* Common Aggregate Iterator Functions That Deliver a Single Output:​
	+ SUMX delivers an aggregate sum value​
	+ AVERAGEX delivers an aggregate average value​
	+ MAXX/MINX delivers an aggregate max value​
	+ CONCATENATEX delivers a text string with joined items​
* Common Aggregate Iterator Functions That Deliver a Table:​
	+ FILTER delivers a table of values​
	+ ADDCOLUMNS delivers a table of values

An iterator function in DAX takes in the table and the expression as arguments. An iterator function example is as follows:

Sales Table
 2
 3

```
Revenue = SUMX(Sales, Sales[Unit Price] * Sales[Order Quantity])
```

Revenue = $2,000

An iterator function in DAX becomes very useful when you are working with large amounts of data. Rather than having to store the data in a calculated column, iterator functions allow you to aggregate the results into a single output.

## Modifying Filter Context

Filter Context describes the filters that are applied to a measure or measure expression.

Filters can be applied through the filters pane to specify the data we want to visualize. DAX lets us add, modify, and remove filters to help achieve our desired result by using the CALCULATE function

```
CALCULATE(<expression>, [[filter1], filter2]...)

```

There are 2 types of filters:

Boolean Expression Filters

* Evaluates to TRUE or FALSE
* Can only reference a single column
* Cannot reference measures
* Cannot use functions that scan or return a table that include aggregation functions like SUM

```
Revenue Expensive Products = CALCULATE([Revenue], 'Product'[List Price] > 1000)

```

Table Expression Filters

* Uses the FILTER function
* An iterator function that lets you pass in an expression to evaluate each row of the table

```
Revenue High Margin Products =
CALCULATE(
    [Revenue],
    FILTER(
        'Product',
        'Product'[List Price] > 'Product'[Standard Cost] * 2
    )
)

```

**Filter Modifiers**

We can change the way filters interact with our measures by using filter modifier functions

* ALL
* ALLEXCEPT
* REMOVEFILTERS
* KEEPFILTERS
* USERELATIONSHIP
* CROSSFILTER

For example, if we wanted to produce a total of a table which ignores any filters applied to that table we can use the REMOVEFILTERS function in a measure to ignore any filters applied to the 'Sales Territory' table

```
Revenue Total Region = CALCULATE([Revenue], REMOVEFILTERS('Sales Territory'))

```

This total can be used as a denominator in various ratios to obtain a percentage of the grand total

We can also use the USERELATIONSHIP function in CALCULATE to make an inactive relationship active. Doing this will make the current active relationship inactive

```
Revenue Shipped =
CALCULATE (
    [Revenue],
    USERELATIONSHIP('Date'[DateKey], Sales[ShipDateKey])
)

```

**Examining Filter Context**

* VALUES
* HASONEVALUE
* SELECTEDVALUE
* ISFILTERED
* ISCROSSFILTERED
* ISINSCOPE

We can use the VALUES function to return the values of a table or column in filter context. When used in conjunction with HASONEVALUE we can return all values of a table that contain only one value in filter context

```
Sales Commission =
[Revenue]
    * IF(
        HASONEVALUE('Sales Territory'[Country]),
        IF(
            VALUES('Sales Territory'[Country]) = "United States",
            0.15,
            0.1
        )
    )

```

The measure will return values for all cases where HASONEVALUE returns true

## Time Intelligence Functions

Time Intelligence functions enable you to manipulate data using time periods and build and compare calculations over those periods.

Time Intelligence functions include but aren't limited to:

* SAMEPERIODLASTYEAR( )
* TOTALYTD( )
* DATEADD( )
* DATESBETWEEN( )
* TOTALMTD( )

Each Time Intelligence Function falls into two categories. They are either DAX Date functions or DAX Date Calculation functions. Date functions return a single date, date column, or date table. Date Calculation functions return a single value measure from an inputted expression.

An example of a TOTALYTD( ) is:

```
TOTAL Measure =
TOTALYTD(
    SUM('Sales'[Sales Amount]),
    'Dates'[Date]
)
```

An example of SAMEPERIODLASTYEAR( ) is:

```
Rolling 12 Months PY Revenue =
CALCULATE(
    SUM('Sales'[Sales Amount]),
    SAMEPERIODLASTYEAR('Dates'[Date])
)
```

## References

* Microsoft Data Analysis Expressions (DAX) Reference (https://learn.microsoft.com/en-us/dax/)
* Microsoft Training: Use DAX in Power BI Desktop (https://learn.microsoft.com/en-us/training/paths/dax-power-bi/)
* Microsoft Learn DAX basics in Power BI Desktop (https://learn.microsoft.com/en-us/power-bi/transform-model/desktop-quickstart-learn-dax-basics)
* Microsoft Power BI Courses: DAX in a Day (https://powerbi.microsoft.com/en-us/instructor-led-training/)

## Authors

Alex Byczkowski, Samantha Gorder, Cayle Jones, Dawson Porter