Você está na página 1de 179

DAX

Your Definitive Guide to Learn and


Write DAX

By Adrian Venice
Contents

Introduction
Chapter 1 Why You Need to Learn DAX
Measures
Explicit Measures
Implicit Measures
How to name Measures
Calculated Columns
Naming Calculated Columns
Chapter 2 How DAX Works in Power Pivot
Creating Formulas
Relational Model Formulas
How to Update Results
Chapter 3 DAX Syntax
Filter Context
Row Context
Formulas for Measures
Formulas for Calculated Columns
AutoSum Formula
Adding Functions to Formulas
Chapter 4 DAX Data Types
Explicit and Implicit Data Type Conversion
Implicit Data Conversions
(+) Addition
(-) Subtraction
(*) Multiplication
(/) Division
Operators for Comparison
Empty Strings, Blanks, Zero Values
Chapter 5 Date and Time Functions
Calendar Function
CalendarAuto Function
Date Function
EOMonth Function
Hour Function
Minute Function
Now Function
Time Function
Today Function
Weekday Function
WeekNum Function
Year Function
Chapter 6 Time Intelligence Function
Closing Balance Month Function
Closing Balance Quarter Function
Closing Balance Year Function
DatesBetween Function
DateAdd Function
DatesInPeriod Function
DatesQtd Function
DatesMtd Function
FirstDate Function
EndofYear Function
EndofMonth Function
FirstNonBlank Function
NextDay Function
Opening Balance Month Function
SamePeriodLastYear Function
TotalMTD Function
Chapter 7 Information Functions
CustomData Function
Contains Function
IsError Function
IsBlank Function
IsNonText Function
IsoNoRafter Function
IsNumber Function
IsText Function
Username Function
LookUp Value
Chapter 8 Filter Functions
All Function
AllNoBlankRow Function
Add Missing Items Function
All Selected Function
Calculate Function
CrossFilter Function
Earlier Function
Related Function
Values Function
UserRelationship Function
KeepFilters Function
Chapter 9 Logical Functions
And Function
False Function
Not Function
IF Function
IFError Function
True Function
Switch Function
Or Function
Chapter 10: Text Functions
Blank Function
Pre-Defined Numeric Format Function
Pre-Defined Date and Time Format Function
Custom Numeric Formats Function
Custom Date and Time Format Function
Code Function
Find Function
Chapter 11 Parent Child Function
Path Function
Path Item Function
PathLength Function
Chapter 12 Statistical Functions
CrossJoin Function
Generate Function
DataTable Function
Count Function
Average Function
Summarize Columns Function
GroupBy Function
GenerateAll Function
Arrange Function
Chapter 13 DAX Exercises and Puzzles
Data Lineage
In Query Puzzle
Many-to-Many Relationships
Show Active Orders
Data Import
Filtering Columns
Filter Calculate Puzzles
Use Relationship Puzzle
Chapter 14 Troubleshooting and Final Tips
Tips to Keep in Mind
Conclusion
Introduction

I want to thank and congratulate you for purchasing the book “DAX: Your
Definitive Guide to Learn and Write DAX”
Fairly a new part of the programming and calculation niche, DAX, or Data
Analysis Expressions formula, is now considered as one of the most important
functions in the said niche—and more! Basically, it is a collection of
operators, functions, and constants that you can then use in expressions or
formulas to calculate one or more returned values. This means that with the
help of DAX, you get to create new information with your model, and this can
then be part of your data.
With the help of this book, you will understand why it is important to learn
about DAX, and what exactly should you do to help yourself write DAX
without having any problems. From the basics of measures and calculation and
everything else you need to know, you’ll find them all right here.
Read this book now to find out how.
Once again, thank you, and good luck!
Chapter 1 Why You Need to Learn DAX

As mentioned earlier, DAX is a big collection of functions, constants, and


operators that could help you create new data. For example, if you are writing
something and your pen loses ink—and you have no pencil around, would you
be able to continue writing? Probably not, right? That’s exactly how DAX
works—and more!
Aside from writing data, DAX also helps you calculate and make sense of it.
With the help of DAX, you’d also be able to create new workbooks and make
sure you’d be able to put data in them. You might also get to create Pivot
Charts and Tables, combine inventory data, and formulate data that will help
you—and whoever the data is for, too. When you have the right formulas,
you’d get the exact information you need—and you’ll get to solve problems
involving your business, too!
If you’d like to learn about DAX, it would definitely help out if you already
know the basics of Measures, and Calculated Columns. If not, or if you’re
having a hard time recalling these things, here’s a refresher for you.
Measures
It was in Power Pivot, Excel 2013 that Measures first came into full fruition.
Basically, when it comes to data analysis, measures are the calculations you
use. These calculations include averages, sums, counts, minimum or maximum
values using a DAX Formula—which you’ll learn more about in the next
chapter.
Measures are placed in the VALUES area. Columns and rows that surround it
would then help you determine the value that you need. So, for example, if
you’re dealing with customer orders and the amount of sales, the value that you
need will be computed based on the given elements.
Measures could either be explicit or implicit, depending on the situation. This
will then affect how you’d use them on the charts or other applications.

Explicit Measures
You can create explicit measures when formulas are typed or selected in the
calculation areas, with the help of AutoSum. An example of an explicit
measure is shown below:

https://support.content.office.net/en-us/media/c45844f4-5ec7-4ec6-871d-a07e7d4fa24c.jpg

You can use explicit measures in any Pivot Charts or Tables that you are
working on. They could also be converted to KPI by using numeric data or
strings that you have. Take note that you can only use the KPI command, and
Format when you are dealing with explicit measures.
Implicit Measures
Meanwhile, implicit measures can be used for standard aggregation purposes
—examples include COUNT, SUM, MAX, MIN, AVG, or DISTINCTCOUNT
functions, and should readily be defined for the purpose of aggregation.
An example of an implicit measure is given below:

http://i.stack.imgur.com/5vaK8.png

How to name Measures


In order to rename or rearrange measures, you have to keep the following in
mind:
1. Each measure in a table should be unique in itself.
2. You can find measures in the Fields list of Pivot Tables—unless they are
hidden, of course. Make sure that when you name or rename them, you’d do
so in such a way that would easily reflect what they are trying to perform.
3. Some characters cannot be used in a name, such as *$&. If you’re going to
use other characters such as Cyrillics, make sure that you enclose them in
quotation marks (“”).
4. Any formulas that can invoke other formulas have to be updated once you
have renamed a measure. Make sure formulas would be updated
automatically or else you’d have to take your time with these.
5. Make sure that you avoid names that you have already used for other
columns earlier.
Calculated Columns
Meanwhile, calculated columns have the distinction of helping you add new
data to the tables that you have in your Power Pivot Data model, where you’d
get to make formulas that can derive what’s on the given columns.
The formula mostly used here is =[SalesAmount]-[TotalCost]-
[ReturnAmount] which is then calculated by working on values from each row
by subtracting them from the total cost and return amount columns. What you
can then use for your Pivot Table is your Profit column, just like what’s shown
below:

http://www.teachucomp.com/wp-content/uploads/blog-3-22-2016-
CreateCalculatedColumnsInPowerPivotInExcel2016.png

Basically, if you know how to create formulas in Excel, that’s also what you
should be doing with Calculated Columns. The difference is that different rows
cannot have different formulas in them, unlike in Excel.
If a certain column contains a formula, you can then compute value for each
row that you see, and the results will then be calculated and recalculated, as
necessary. With the help of measures, you can then create other calculated
columns where you can extract strings of text from.

Naming Calculated Columns


In order to name calculated columns properly, make sure that you keep the
following in mind:
1. Do not use the same names that you have already used for your measures.
2. Each column, just like each measure, should also be unique within a table.
3. Refer to measures’ naming requirements to check if you’re using the right
name for your columns.
4. Update formulas on your columns once you have renamed them.
Chapter 2 How DAX Works in Power Pivot

To understand how DAX works in Power Pivot, it would be good to begin by


comparing it to Excel Functions. What exactly differentiates them from each
other? How are DAX formulas unique? Well, here’s what you need to know:
1. DAX functions don’t necessarily take cell references, as well as range
references, but could take tables or columns as reference.
2. DAX functions also have the same general behavior and name as Excel
functions, and could be modified for different types of inputs. You cannot
use these in Power Pivots or Excel Formulas without modification.
3. Data in columns are often expected to be the same data type, and you have
to keep in mind that DAX could change the entire column to the data type
that could then accommodate all values.
4. New lookup functions are provided by DAX. These may be similar to array
and vector functions, but you do have to take note that there should be an
established relationship between the tables before you use DAX.
5. New DAX functions could also make calculations or return table values
based on what you have inputted in the table of values itself. This way,
rows and columns could easily be referenced.
6. A daytime data type could be returned by certain DAX functions as
reference, and could also return integers that show serial numbers as
represented dates.
Creating Formulas
To create DAX formulas, you do have to make use of the Formula Bar that
you’d see on Power Pivot.
In order to enter table name, you should type what you’d want to call the table.
You can then see a dropdown list containing names that are valid, and the valid
characters that you can use, too.
As for the column name, you should begin by typing a bracket, and then you
should choose the column you want from the list of columns that you’d see
onscreen.
As you’d notice, AutoComplete is prevalent here, but you can also work on
AutoComplete by formulating the said bar. To do so, you should fill up a
formula in the nested functions, and when you see some text displayed
onscreen, you should then create free constants—or elements that you want to
be seen in your column name. Make sure that each function is in sync with the
formula you’re trying to use, or else it wouldn’t really work the way you want
it to.
Relational Model Formulas
If you’d get to work with multiple tables of data, you have to keep in mind that
you can do so in the Power Pivot window. By doing so, you’d get to make sure
that tables are connected to one another, and that correlations between rows
and columns could then begin at this point. Filters could also then be applied to
tables and columns, but you have to make sure that calculations are designed
differently so that you could do more than what you’re used to in Excel. For
this, you have to remember the following:
1. Each table should have the same number of columns in each row. You also
have to remember that each of the rows should have the same data types.
2. Each DAX formula should be applied to the entire set of values in one
column.
3. You’d have to use “relationships” to link tables together. To do so, you’d
have to manage context, or enlarge the scope of formulas that you are trying
to evaluate. The Pivot table could then be affected by row headings and
columns, and you can then manipulate the formulas through context that can
be used for manipulation.
4. You also have to make sure that your key columns have the same values,
especially if they’re used to connect “relationships” in your data.
Referential integrity is not enforced by Power Pivot—so make sure that
you’d have the same key values to make sure that things will be easier for
you.
How to Update Results
Formula results also have to be updated from time to time, and the process is
called Recalculation and Data Refresh. To do so, you have to remember that
the result of formula for each calculated column should also change whenever
you change the formula. You also have to remember that the results of the said
formula would not be calculated until you have placed data on the context of
PivotChart or PivotTable. If you’re going to change headings of rows and
columns, you should also have the formula recalculated.
Chapter 3 DAX Syntax

Of course, in order to write DAX, it’s just imperative that you learn its syntax.
While it was mentioned earlier that you can write your own formulas, you do
have to keep in mind that starting with what’s basic is essential. Here’s a
sample formula that’s often used:

https://support.content.office.net/en-us/media/35eb88e7-e8a9-4d13-a8c1-9bc3d595c1a9.jpg

What you can see in the formula above is that:


1. [SalesAmount], which is also known as the referenced column, holds the
values that you want something to be extracted from. This is then
surrounded by brackets. DAX formulas often reference columns, as
compared to excel formulas that reference cells.
2. The = sign, or Equals Sign, shows you that the formula has begun, and that
it will then be calculated when a value or result has been returned. You’d
always see the Equals Sign whenever you get to calculate a value.
3. [TotalCost], another referenced column, shows the values that you want to
be subtracted from what’s in the [SalesAmount] column.
4. “-“ or the subtraction sign is then used as the mathematical operator here.
So, if you want to use this syntax for a measure, you have to tweak it a bit so
that the end result will be something like the one shown below:
https://support.content.office.net/en-us/media/36eac5cc-400b-4ff8-b2c9-f5e2953cfb45.jpg

What you can see from the edited syntax is that:


1. The beginning of the calculation formula is seen through the “=” sign. You’d
get a result after calculation is done.
2. [SalesAmount] or the referenced column here is the FactSales table. You’d
be able to aggregate the right SUM because of the fact that the SUM
function would be able to show it.
3. You could also see that one or more arguments are enclosed in parenthesis
(), which means that each function requires one argument. By creating
arguments, you’d get to make sure that values are passed to functions.
4. SUM would add up [SalesAmount] values to give you a proper total.
Filter Context
Another way for you to understand how DAX Syntax works is by learning
more about Filter Context.
Basically, Filter Context is about the filters used to determine values by means
of calculation. You can use this with row context—which you’ll be learning
about below, and you can use it if you want to keep narrowing your choices
down, so that the PivotTables would easily show you what you want to happen.
Filter Context helps you define what goes into your table. For this, you can use
CALCULATE, FILTER, RELATED, or ALL.

https://support.content.office.net/en-us/media/7cd32f6f-ffd2-4bde-a638-7e79e6c2d37d.jpg

Judging from the illustration, it’s safe to say that what you’d get is that:
1. StoreSales is the measure name—and the name for filtered context should
always be followed by a column.
2. An expression could be evaluated with the help of the CALCULATE
function. The specified filters would then help you evaluate this argument.
3. One or more arguments could be surrounded by a parenthesis ().
4. In the same expression, you can keep in mind that you can measure Sales
through the formula =SUM(FactSales[SalesAmount]).
5. DimChannel is a filter for the referenced column, and the particular value,
as well.
6. Each filter could be separated by a comma.
7. [Sales] could be measured in the same table as the expressions that you
have. For this, you have to use the formula
=SUM(FactSales[SalesAmount]).
Row Context
Row Context is quite simple as compared to Filter Context.
Basically, for the given examples earlier, you can conclude that [SalesAmount]
could calculate VALUE in the TotalCost Margin if they are on the same row—
kind of reminiscent of how it goes on Excel. Then, you could get something
like the example below:

https://support.content.office.net/en-us/media/210bbb3c-e160-40a4-9621-11819240d3ee.jpg
Formulas for Measures
Try what you have just learned by trying to create a formula for your measures.
Let’s use the example of the FactSales table. What you can do is click an empty
cell in the calculation area, just below the Power Pivot window, just like
what’s shown below:

https://support.content.office.net/en-us/media/c864f781-b0e3-4905-a32e-cc708c9b14c7.jpg

Then, follow the instructions below:


1. Type Previous Quarter Sales in the formula bar.
2. Then, begin calculation by typing “=” or the Equals Sign.
3. Type CAL before double-clicking the function. Use CALCULATE.
4. Type ( or opening parenthesis.
5. Type the first few letters of FactSales, and then double click FactSales from
the drop down list.
6. Specify filter by typing a comma (,) and then go ahead and type PRE. A
dropdown box will show you PREVIOUS QUARTER SALES. Go ahead
and click it.
7. Type DIM, then go and double-click the key for [DateKey] which is DIM
DATE.
8. Type ) or closing parenthesis.
9. You should then see something like this onscreen: CALCULATE
(FactSales[Sales], PREVIOUSQUARTER (DimDate[DateKey])).
10. Validate formula by clicking the Check button on the formula bar. Verify
each syntax if an error shows up onscreen.
Formulas for Calculated Columns
Another great way to start would be to create a formula for your calculated
columns. Again, you’d have to start by clicking the FactSales table in Power
Pivot. After doing so, go and click the formula bar on the designer window,
like what’s shown below:

https://support.content.office.net/en-us/media/19413f32-3eda-4165-bc51-b7b69ac175f9.jpg

Then, follow the instructions below:


1. Type = or the equals sign in the formula bar. You can always start with a
bracket [, and after doing so, you’d see a small window appearing on the
table. Take note that there is no more need to precede the column name
before you get to press Tab and see that the cursor is now pointing to
[SalesQuantity].
2. Type a subtraction operator “-“ after typing a space. Then, go ahead and
type another space.
3. Type an opening bracket [ before selecting [ReturnQuantity], and then go
ahead and press Enter.
4. On the column header, do a right click on NetSales, and you’d have created
a formula for your calculated columns!
AutoSum Formula
Once of the easiest formulas you can make is the AutoSum. Here’s how you
can work on it:
1. Scroll to ReturnQuantity in the FactSales table. After doing so, go ahead
and select the whole column from the column header.
2. On the ribbon that you see on the Home tab, click AutoSum in the
Calculations group, just like what you see below:

https://support.content.office.net/en-us/media/f134596c-b135-478f-af35-e84ddd84e930.jpg

3. Click the arrow that you see next to AutoSum.


4. After doing so, click Average, and then you’d see a new measure saying
that Average of ReturnQuantity has been created as a measure, and then you
should see this formula: =AVERAGE ([ReturnQuantity]).
That’s it! You have no created a good AutoSum Formula for yourself!
Adding Functions to Formulas
Another basic thing you can do is add functions to formulas by doing the
following:
1. Scroll to the rightmost column of the FactSales table, and click Add
Column in the header.
2. Type = or the Equals sign in the formula bar.
3. Click the Insert Function, or the one shown below:

https://support.content.office.net/en-us/media/fbf240fa-ca8c-4de4-ab08-bfd0cab07116.jpg
4. Click Select in the Insert Function box, and then select your chosen
category from the dropdown list.
5. Try to have some data returned by clicking the Filter category, and then
choose Select. Scroll down, and then go ahead and double click the said
related function. Click OK.
6. Select DimChannel from the dropdown list, and then close the formula and
press Enter.
7. You’ll now see that you have created a new column on the FactSales table.
You can now focus on renaming the channel, until you end up with
something like this: =RELATED(DimChannel[ChannelName])
Chapter 4 DAX Data Types

DAX also makes use of Data Types that will help you create various kinds of
formulas. This chapter will also help you differentiate Data Types in DAX and
in Excel. Here’s what you can keep in mind:
Data Type in DAX Data Type in Excel Description
String Text These are Unicode
characters that could either
be numbers, strings, or data
dates that are represented in
text format. The maximum
string length is 256
characters, or 268,435,456
Unicode characters.

Date/Time Date For this, date-time


representation is accepted.
Dates that are deemed valid
are those that are past
January 1, 1900.
Currency Currency
Boolean True/False This value could either be
true or false.
64-bit Real Number Decimal Number These are numbers that have
decimal places, and cover a
wide value range. These
cover negative values from
1.79E to 2.23 E. It could
also denote Zero, and could
also have positive values
from 2.23 E to 1.79 E and
has significant number of
digits with a 15 decimal
digits limit.
64-bit Integer Whole Number These are numbers that do
not have decimal places.
These could either be
negative or positive numbers
that are between
-9,223,372,036,854,775,808
and
9,223,372,036,854,775,807.
Blank N/A This is a data type that could
represent SQL Nulls, and
could be created using the
Blank Function, or the
ISBLANK logical function.

What you can take from the given table is that DAX Expressions do not
necessarily support data types that are not listed there. Large numeric values
could also easily be imported.
Also, when you try to import extremely large numeric values as data, chances
are, you might get the following error through import fail:
In-memory DB error: The '<column name>' column of the '<table name>'
table contains the value, '1.7976931348623157e+308', which isn’t
supported. The operation is cancelled.
That happens because Power Pivot does not have the capacity to understand
null values, such as: 9223372036854775807, 2.2250738585072014e-308,
1.7976931348623158e+308, or -9223372036854775808. If that’s the case,
you’d just have to start again.
Explicit and Implicit Data Type Conversion
You have to remember that data type conversion makes use of its own specific
requirements because there are always different inputs and outputs that you
have to deal with.
If you can specify an argument in the data column, your argument would then be
incompatible w/ the data type that you are trying to use. So, in order to make
sure that you’d get to convert explicit and implicit data the right way. Here’s
what you have to keep in mind:
1. Data could be typed as string. DAX will then be able to parse the string so
that it could be cast through Windows famous date and time formats.
2. If you have two columns and you’d add two values there, one of the values
would be represented as “12” while the other would be represented as
numeric result, giving you something that looks like this: 44: “22” + 22
3. If you’d add the word TRUE +1, you can expect that you’d get the result of
2. Why? Well, simply because you now were able to covert 1 implicitly
into TRUE, while the 1 + 1 operation is being performed.
4. If you’re trying to concentrate on 2 numbers, you can expect Excel to
present them as strings. So if you have “5678”, it will be returned as “56”
and “78”.
Implicit Data Conversions
This is the kind of conversion that is determined and performed by the operator
itself. For this, you have the following:

(+) Addition
For this, you would notice that a real number could be used in addition
operations together with values, and the currency data, as well. So, when you
convert something to REAL, the result would be REAL, as well.

(-) Subtraction
Now, in this table, you would see that the minuend or the row header is on the
left side. Therefore, the subtrahend is then located on the right side.

(*) Multiplication
For multiplication, you can expect that if you combine a real number with an
integer, you could have both of them converted to real numbers. The return
value would also then be REAL.
(/) Division
For Division, you would notice that the operator is also the row header, which
also serves as the numerator, and that the denominator is known to be the
column header. If integers are combined, both values would have to be
converted to real numbers, and the result you’d get would also be a real
number, as well.
Operators for Comparison
One such time that Boolean Values could be considered higher than string
values is by means of Comparison, and using operators for the said event.
String Values are often considered to be greater than date/time values, and
other numerics and could be considered to be on the same rank, without any
implicit conversions being performed. With that in mind, it’s safe to say that
you’d see the following:

Empty Strings, Blanks, Zero Values


The same value type represents empty cells and blank values. This is basically
called “The Blank”.
Blanks are handled in operations in different ways, depending on the
individual functions. You can refer to the table below so you’d understand
more about what this is about.

Expression DAX Excel


Blank + Blank Blank 0 (zero)
Blank * 5 Blank 0 (zero)
Blank + 5 Blank 0 (zero)
0/ Blank NaN Error
5/ Blank Infinity Error
False or Blank False False
Blank / Blank Blank Error
True or Blank True True
False and Blank False False
Blank or Blank Blank Error
True and Blank False True
Blank and Blank Blank Error

In the next chapters, you will learn more about how each function works so you
could understand this better!
Chapter 5 Date and Time Functions

As the name suggests, you could already denote that these functions have a lot
to do with date and time—and would make calculations based on those. If you
know Excel’s date and time functions, you might notice that these are similar to
those.
Calendar Function
This function works on a single column by returning a table to you a table that
contains “Date” data, which means that there is a contiguous set of dates
involved in the process. The specified start and end dates are included in the
range of dates.
Its syntax is:
CALENDAR(<start_date>, <end_date>)
You can find this in Power Pivot 2016, as well as in SQL Server 2016.
Using <start_date> means that a datetime value should be returned. Same goes
for <End_date>. If start date is greater than end date, you can expect that an
error would occur.
Return Value
This means that when a single table has a “Date” column, you can expect that
you’d see results with a contiguous set of dates, with specified start and end
dates.
CalendarAuto Function
Meanwhile, this function would bring you s column named “Date”, which in
itself is a contiguous set of dates. These dates are based on the given model. Its
syntax is:
CALENDAR(<start_date>, <end_date>)
This DAX expression returns an integer between the numbers 1 to 12. You can
have this omitted, but once you do so, you can expect that the value for the
calendar template would come back to default. However, if this is present, you
can expect the value to return to 12.
The range of the date could then be calculated as follows:
1. First, there should be the earliest date in your example. This should not be
in any calculated table or column, and should be taken as MinDate.
2. It should also include the latest date in the model which should not be in a
calculated table or column. This should then be the MaxDate.
3. Therefore, the date range that you’ll get should be between the start of the
fiscal year, and the end of the year—or between Min and Max Dates.
Date Function
This basically just returns the date in a datetime format. It uses this syntax:
DATE(<year>, <month>, <day>)
There are also certain parameters that make it what it is. For this, you’d have
to remember the following:
Day. This should be a number representing the day that could be calculated if
the day is a number starting from 1 up to the last day of the given month.
However, if you input a number greater than the last day of the month, the date
will then be calculated by adding the value of the day to the month. Then, if you
enter a negative integer, you can expect that once you subtract the value of day
from month, that would then be your result as the day.
Month. This should be a number that would represent a particular month. If a
number is between 1 to 12, it automatically—at least, for this purpose—
represent a month of the given year. Each of the 12 numbers represent a month,
starting with January (1) and ending with December (12). However, if you
input a value that’s larger than 12, you’d then be able to calculate the date by
adding the value of the month to the value of the year.
Year. Of course, this is a number that would then represent a given year. This
could include 1 to 4 digits, and would automatically be interpreted by your
computer. Any date after March 1, 1900 would be supported. However, if
you’re going to input anything lower than 1900, what would happen is that the
value would be added to 1900 so you could get your result.
EOMonth Function
Meanwhile, this function will give you the date in the datetime format for the
last day of the month. It could also provide results after a specified number of
months, and can calculate due dates or maturity dates, as well.
Its syntax is:
DATE(<year>, <month>, <day>)
The start_date here determines the datetime format’s start date. It could also
give the accepted text representation of a given date. The Months would then
determine the number of months that have occurred before the start date.
You would then get an error if the program sees that start_date is not valid. If it
is a numeric value, instead of being a datetime value, you can then expect that
it would be converted to a date but might also return an error.
Hour Function
The Hour Function would give you the result taken between integers of 0 to 23.
It uses the following syntax:
HOUR(<datetime>)
This also makes use of the argument about the time where the hour you want to
find is contained. The date/time function would supply you with this function.
This uses the date/time or locale settings of the computer, as well.
If a text representation of the given date/time is present, the date/time locale is
also used, although conversion would have to be imminent.
Minute Function
This function gives you minute, which is a number between 0 to 59. It uses the
syntax:
MINUTE(<datetime>)
It also deals with accepted date/time formats, and does not store data in serial
numeric formats like Excel does.
Now Function
This returns the current time and date in a datetime format. It uses the syntax
below:
NOW()
The result only changes when you refresh the column that contains this given
formula, so even if it’s already a different day, if you haven’t refreshed the said
column, no changes will happen. Another problem is that it is not accurate
when it comes to the representation of time.
Time Function
This function converts specific seconds, minutes, and hours into a datetime
format, and uses the following syntax:
TIME(hour, minute, second)
It also covers the following parameters:
Second. This is a number between 0 to 59 that represents the second, and
anything above it will then be converted to seconds, minutes, and hours.
Minute. This is any number from 0 to 59 that represents the given minute, and
anything above it will be converted to minutes and hours.
Hour. This is a number from 0 to 23 that represents the current or the given
hour, and anything above will be divided by 24 and be regarded as a whole
value.
It is also recommended that you format the PivotTable cell or column so that
readability would become better.
Today Function
This function is helpful when you need to have the current date displayed on
certain worksheet no matter how you open the workbook. This function is also
used to calculate intervals, and uses the following syntax:
TODAY ()
If NOW gives the current time, TODAY shows the time as 12:00 PM no matter
what date it is.
Weekday Function
This function returns a number between 1 to 7, which would then be noted as a
certain day of the week. It uses the following syntax:
WEEKDAY(<date>, <return_type>)
It covers the date, as well as the following parameters:
1. The week begins on Sunday (1) and ends on Saturday (7).
2. Week begins on Monday (0), and should end on Sunday (6), but should still
be numbered 1 to 7.
3. Week begins on Monday (1) and ends on Sunday (7).
WeekNum Function
Meanwhile, this function is all about the given week and year, and should be
determined according to return_type. It uses the following syntax:
WEEKNUM(<date>, <return_type>)
It also covers the following parameters, aside from date:
1. Week begins on Monday, and weekdays should be numbered 1 to 7.
2. Week begins on Sunday, and weekdays are numbered 1 to 7.
Year Function
This returns a four-digit integer that would serve as the year of a given date,
and is in the range 1900 to 1999. It should be entered using the Date Function,
and uses the following syntax:
YEAR(<date>)
Chapter 6 Time Intelligence Function

The great thing about DAX is that it is perfect for Business Intelligence. This
happens in such a way that it is able to help you manipulate data by making use
of years, quarters, months, and days. From those, you can then go ahead and
build calculations and have those calculations compared, too. This covers the
following areas:
Closing Balance Month Function
This function denotes the last day of the given month based on the current
context. It makes use of the following syntax:
YEAR(<date>)
This covers the following parameters:
1. A column for dates. This could either be a reference to a given time or date
column; a table expression that’s able to return a certain column, or; a
Boolean expression for single columns of the datetime kind.
2. Expression column, or one which returns a scalar value.
3. An optional filter, in case you want a filter to be applied to the current
context.
Closing Balance Quarter Function
This denotes the last date of a given quarter, and uses the syntax given below:
CLOSINGBALANCEQUARTER(<expression>,<dates>[,<filter>])
It also covers the following parameters:
1. A column for dates. This could either be a reference to a given time or date
column; a table expression that’s able to return a certain column, or; a
Boolean expression for single columns of the datetime kind.
2. Expression column, or one which returns a scalar value.
3. An optional filter, in case you want a filter to be applied to the current
context.
Closing Balance Year Function
This one is about the last date of the current year in a given context.
It uses the following syntax:
CLOSINGBALANCEYEAR(<expression>,<dates>[,<filter>][,
<year_end_date>])
It covers the following parameters:
1. A column for dates. This could either be a reference to a given time or date
column; a table expression that’s able to return a certain column, or; a
Boolean expression for single columns of the datetime kind.
2. Expression column, or one which returns a scalar value.
3. An optional filter, in case you want a filter to be applied to the current
context.
4. An optional yearend date that is just a literal string for the yearend date
DatesBetween Function
This function will give you a table that contains dates within a column that
begins with the start_date and ends with end_date. It uses the following syntax:
DATESBETWEEN(<dates>,<start_date>,<end_date>)
This function covers the following parameters:
1. Start_date, or a date expression;
2. Dates, or references to date/time columns, and;
3. End_date, or a date expression itself.
DateAdd Function
If you have a column of dates that you want you get, then that’s where you need
this function for. The dates would then be shifted forwards or backwards in
time with intervals in a current given context. This function uses the following
syntax:
DATEADD(<dates>,<number_of_intervals>,<interval>)
This covers the following parameters:
1. Dates, or a certain column that defines dates;
2. Interval, or the interval that you want to use to have the dates shifted, and;
3. Number of Intervals, or the number of intervals you’re actually going to
use.
DatesInPeriod Function
Meanwhile, this function will be able to provide you with a column that begins
with the start_date, and would then continue for a specific number of intervals.
This uses the syntax below:
DATESINPERIOD(<dates>,<start_date>,<number_of_intervals>,
<interval>)
It contains the following parameters:
1. Dates, or a certain column that defines dates;
2. Start Date, or when the list should start;
3. Interval, or the interval that you want to use to have the dates shifted, and;
4. Number of Intervals, or the number of intervals you’re actually going to
use.
DatesQtd Function
Mainly, this is used to denote the dates for the given quarter up to the current
date. It uses the following syntax:
DATESQTD(<dates>)
It is used to reference date/time columns, and could return single columns of
date/time values. It could also define single columns of date/time values, as
well. It also uses the following parameters:
1. References to a date/time column;
2. Boolean Expressions that define single column tables, or;
3. Table expressions that return single column date/time tables.
DatesMtd Function
This could return a table that encompasses a column for the current month to
certain given dates in the current context, and uses the following syntax:
DATESQTD(<dates>)
In order to see how this works, it would be important to create a Pivot Table,
and once you have done so, you can go ahead and add the fields that you need.
FirstDate Function
This gives you back the current context’s first date for a specified number of
dates, and contains the following parameters:
1. References to a date/time column;
2. Boolean Expressions that define single column tables, or;
3. Table expressions that return single column date/time tables.
EndofYear Function
This function returns a value of the last date of the year in a current context,
and makes use of the following syntax:
ENDOFYEAR(<dates> [,<year_end_date>])
This covers the following parameters:
1. The column that contains dates, and;
2. The yearend date, or a literal string that gives you the yearend date.
EndofMonth Function
This gives you back the last date of the month for the current context, and uses
the following syntax:
ENDOFYEAR(<dates> [,<year_end_date>])
This covers the following parameters:
1. References to a date/time column;
2. Boolean Expressions that define single column tables, or;
3. Table expressions that return single column date/time tables.
FirstNonBlank Function
This basically gives you the first value in a certain column, and uses the
following syntax:
FIRSTNONBLANK(<column>,<expression>)
The CALCULATE argument is important here, and you can also take note that
it covers the following parameters.
1. Table expressions that return single column date/time tables;
2. References to a date/time column;
3. Boolean Expressions that define single column tables;
4. Column Expressions, and;
5. Expressions for Blank as you have learned in Chapter 4.
NextDay Function
Basically, this’ll give you back a table that has all of the dates from “next day”
on a given column. It uses the following syntax:
NEXTDAY(<dates>)
What you can keep in mind about this is that it is not supported by DirectQuery,
and you definitely need to create a Pivot table for this, too. You also have to
remember that this will give you back all the dates from the succeeding day all
the way to the input parameter’s first date.
Opening Balance Month Function
The result that this function will give you is the first date of the month in the
current context. For this, you can use the following syntax and input it on the
Pivot Table:
=OPENINGBALANCEMONTH(SUMX(ProductInventory,ProductInventory[UnitCost]*Pr
SamePeriodLastYear Function
This function shows you dates that have been shifted one year back in one
column. It uses the following syntax:
SAMEPERIODLASTYEAR(<dates>)
It works because it uses the following formula DATEADD (dates, -1, year) to
give you accurate representations of the same day, last year.
TotalMTD Function
Basically, this is about the Month-running total of expenses or anything
regarding your business that has to be calculated. This makes use of the
following parameters:
TOTALMTD(<expression>,<dates>[,<filter>])
You have to take note that this is a scalar value, and that the dates that are
evaluated are those that are in the month-to-date, and could involve these
parameters below:
1. A column for dates;
2. A column for the expressions, and;
3. A column for specific filters that you want to use.
Chapter 7 Information Functions

You already know that DAX is about a lot of data—and you know what that
means? It means that there’s a lot more that you have to learn, especially when
it comes to your data.
Information Functions work on the row or cell that is known to be an argument,
and would then tell you if the value that you have can match the expected type.
Here’s what you could use:
CustomData Function
If you’re using the CustomData property, with the help of this function, you can
expect that you’d get a result out of it, from the connection string itself. If the
result comes back as BLANK, it means that you have not defined the property
during connection time. It uses the syntax:
CustomData ()
And it could then be applied by doing this:
=IF(CUSTOMDATA()="OK", "Correct Custom data in the connection
string", "No custom data in the connection string property or unexpected
value")
Contains Function
This function will be able to give you back the value for all the referred sets
that you have by using the syntax below:
CONTAINS(<table>, <columnName>, <value>[, <columnName>, <value>]
…)
The return value would be TRUE if you’re able to find the specified value in a
given column alone. However, the value would be FALSE if the information
you are looking for cannot be found in the said column.
It covers the following parameters:
1. Value, or any expression (in DAX terms) could return a single scalar value;
2. ColumnName, or the name of any existing columns, or;
3. Table, or anything that has table data.
You also have to keep in mind that ColumnName has to belong to one specific
table, and should come in pairs with Value. If ColumnName is proven to be
related to a table, then you have to assume that it has to be fully qualified.
Try to apply it by doing this:
=CONTAINS(InternetSales, [ProductKey], 214, [CustomerKey], 11185)
IsError Function
This could help you check whether a value is an error, and would return either
TRUE or FALSE values to you. It uses the following syntax:
ISERROR(<value>)
It covers the VALUE Parameter, and would return the Boolean Value of TRUE
if the particular element is considered to be an error. Otherwise, it would
return a FALSE value.
This is mostly used to calculate errors by calculating Sales Ratio, and to check
for errors by means of dividing by zero. Here’s a good example:
= IF( ISERROR(
SUM('ResellerSales_USD'[SalesAmount_USD])
/SUM('InternetSales_USD'[SalesAmount_USD])
)
, BLANK()
, SUM('ResellerSales_USD'[SalesAmount_USD])
/SUM('InternetSales_USD'[SalesAmount_USD])
)
IsBlank Function
Meanwhile, this function checks whether a certain value can be considered
Blank or not. It uses the syntax:
ISBLANK <value>
It returns the Boolean value of TRUE if there’s a given blank expression.
Otherwise, it returns the value of FALSE. One good example of how this could
be used is for checking how amount of sales have changed from the previous
years. Here, you have to try to avoid dividing a number by zero. For this, you
can use the following formula:
//Sales to Previous Year Ratio

=IF( ISBLANK('CalculatedMeasures'[PreviousYearTotalSales])
, BLANK()
, ( 'CalculatedMeasures'[Total Sales]-
'CalculatedMeasures'[PreviousYearTotalSales] )
/'CalculatedMeasures'[PreviousYearTotalSales])
Doing so will then give you the following result:
Row Labels Total Sales Total Sales Sales to
Previous Year Previous Year
Ratio
2015 $24,542,444.68 $39,248,847.52 -37.47%
2014 $39,248,847.52 $28,553,348.43 37.46%

2013 $28,553,348.43 $10,209,985.08 179.66%


2012 $10,209,985.08
TOTAL $102,554,625.71
IsNonText Function
This helps you check if a value does not involve text—such as blank cells. It
would then give you back either TRUE or FALSE values. You also have to take
note that empty strings are considered “text”, and not blanks. It uses the
following syntax:
ISNONTEXT <value>
You can try it out by coding what’s written below:
//RETURNS: Is Non-Text
=IF(ISNONTEXT(1), "Is Non-Text", "Is Text")

//RETURNS: Is Non-Text
=IF(ISNONTEXT(BLANK()), "Is Non-Text", "Is Text")

//RETURNS: Is Text
=IF(ISNONTEXT(""), "Is Non-Text", "Is Text")
IsoNoRafter Function
Meanwhile, this function has a lot to do with emulating the “Start At” behavior.
If a row meets all the conditions needed, you can expect that the value would
be returned as “True”.
A variable number of triples is taken by this function, with the first two values
compared within the expressions. When all the condition parameters are met,
you can get orders whether in ascending or descending manner, and you can
then have the two parameters compared. However, if the order proves to be
descending, the next parameter would be seen as equal to or greater than the
first parameter.
It uses the following syntax:
ISONORAFTER(<scalar_expression>, <scalar_expression>sort_order]
[,scalar_expression>, <scalar_expression>, [sort_order][,…])
Return Values are True or False, and it also covers the following parameters:
1. Sort Order, or how the column is sorted within an order. It could either be
ASC or DES, or Ascending or Descending.
2. Scalar Expression, or any kind of expression that can return a scalar value,
such as string values, integers, or other references. The column is the first
reference while the second one is known to be a scalar value.
IsNumber Function
This shows you a value as a number, and would return it to be either True or
False, and uses this syntax:
ISNUMBER (<value>)
It tests values and you can try checking out how it works by following the
codes below:
//RETURNS: Is number
=IF(ISNUMBER(0), "Is number", "Is Not number")
//RETURNS: Is number
=IF(ISNUMBER(2.1a-1),"Is number", "Is Not number")
//RETURNS: Is Not number
=IF(ISNUMBER("345"), "Is number", "Is Not number")
IsText Function
This checks if a value could be considered “text”. It returns the value TRUE if
text has been detected. Otherwise, it would return a FALSE value.
It uses the following syntax:
ISTEXT(<value>)
You can then test this function by doing what’s shown below:
Username Function
This function gives you back the username credentials of the members or
followers of your website, and could verify if the user login is part of the
table. For this, you have the following syntax:
USERNAME()
To verify, you can just follow the codes given below:
=IF(CONTAINS(UsersTable,UsersTable[login], USERNAME()), "Allowed",
BLANK())
LookUp Value
LookUp Value could return the value of result_columnName so that all
important criteria, such as search_value, and search_columnname would be
verified, and checked.
This uses the following syntax:
LOOKUPVALUE( <result_columnName>, <search_columnName>,
<search_value>[, <search_columnName>, <search_value>]…)
What you can expect is that the value result_column would be returned when
you have a match for search_value, and search_column, amongst others. If you
cannot have all these values satisfied, you’d have to expect that a BLANK will
be returned, and a lookup will not be returned, especially if you have not met
the given criteria.
Then, if you are going to work on multiple rows, you can expect that search
values would be matched if identical values could be returned.
It covers the following parameters:
1. Search_value, or when the scalar expression does not refer to any specific
columns;
2. Search_columnname, or when you’re trying to search for the name of a
specific column, and could only be searched when using standard DAX
syntax. Otherwise, it would not work, and;
3. Result_columnname, or the name of a column that’s already existing, and
which you want to have a returned value from. You can name this using
standard DAX syntax, as well.
To try this out, just follow the code below:
=LOOKUPVALUE(Product[SafetyStockLevel], [ProductName], " Mountain-
400-W Silver, 46")
Chapter 8 Filter Functions

You probably have been reading about this early on. Well, what you can keep
in mind is that DAX Filter Functions. With the help of Filter Functions, it
becomes easier for you to save and manipulate data the way you want.
For this, you can use the following:
All Function
This function would bring you back all the rows in a certain table. If not that, it
could give you every value in a column, and could also ignore the filters that
might have been applicalbe. You can then clear calculations and create viable
filters with the help of this one.
This uses the following syntax:
ALL( {<table> | <column>[, <column>[, <column>[,…]]]} )
It also covers the following parameters:
1. Column, or where you want the filters to be cleared on, and;
2. Table, or in which table would you want the filters to be cleared on.
What would be returned to you then is the column or table—but with all filters
cleared out. To understand this better, you can look at the table for guidelines
below:
Function and Usage Description
ALL (Table) This function will help you remove
all of the filters from a given table,
and would return all of the values
from the said table. If you are dealing
with many grouping levels, you’d see
that this function is quite useful,
especially when it comes to
aggregation and calculation.
ALL EXCEPT (Table, Column1, With this one, you’d get to remove all
[Column 2]…) of the context filters that you have
applied to the columns you have at
hand. You can also use this as a
shortcut for kinds of situations where
there are lots of filters around.
ALL (Column[, Column[, …]]) If you want to remove filters from
specified columns, you could do so
with the help of this one. The same
table should also bring forth the same
column arguments, as well.

To apply the idea, you can try this example: suppose you want to find the
amount of sales for the cell you are currently working on. For this, you could
use the following code:
SUMX(ResellerSales_USD,ResellerSales_USD[SalesAmount_USD])/SUMX(ALL(Reseller
ResellerSales_USD[SalesAmount_USD])
And then, it will give you a result like the one below:
All Reseller Column Labels
Sales
Row Labels Clothes MakeUp Shoes
2016 30% 70% 50%
2015 20% 30% 50%
Grand Total 50% 100% 100%

For this, it would be easy to use the SUMX Function so you could be sure that
you’d get the right values returned to you!
AllNoBlankRow Function
This function is used for having all rows returned—except for the blank rows.
It could also return the distinct values of columns, except for the blanks, and
would disregard any other filters that may exist. It uses the following syntax:
ALLNOBLANKROW(<table>|<column>)
It also covers the following parameters—and only one of these two could be
passed at a given time:
1. Column, or where the context filters have been removed from, and;
2. Table, or the table where context filters have been removed from.
Take note that this only filters blank rows and columns from the parent table,
and not the parent table itself. This table below will help you understand more
about it:
Usage and Function Description
All (Table) This removes all of the filters from
specified tables
All (Column) This removes all of the filters from
specified columns
ALLNOBLANK (table | column) This returns all the rows from parent
tables of given table relationships,
and could provide distinct values of
columns in rows
ALLEXCEPT (Table, Col1, Col2) This helps you override all context
filters from given tables over
columns that have been specified

To test it out, you can try coding what’s written below:


// Countrows ALLNOBLANK of datetime
= COUNTROWS(ALLNOBLANKROW('DateTime'))
// Countrows ALL of datetime
= COUNTROWS(ALL('DateTime'))
// Countrows ALLNOBLANKROW of ResellerSales_USD
=COUNTROWS(ALLNOBLANKROW('ResellerSales_USD'))
// Countrows ALL of ResellerSales_USD
=COUNTROWS(ALL('ResellerSales_USD'))
What happens with these codes is that:
1. You can now verify unrelated data by opening the Power Pivot Window
and then go ahead and select Reseller Sales (refer to the given table
earlier).
2. Create a Pivot Table, and then drag the datetime column to the pane of the
Row Labels.
3. Then, count all of the rows by using ALL, and also ALLNONBLANK.
4. Now, go ahead and have the count verified.
Add Missing Items Function
Recently introduced, this function helps you out by adding multiple column
combinations of items to one table—even if they have not yet existed before.
You can then evaluate the contents of the columns by using AutoExist, and by
doing so, you can then decide on the combinations that you are going to use.
This uses two syntaxes, which are:
ADDMISSINGITEMS(<showAllColumn>[, <showAllColumn>]…, <table>,
[ROLLUPISSUBTOTAL(]<groupingColumn>[, <isSubtotal_columnName>]
[, <groupingColumn>][, <isSubtotal_columnName>]…[)], [, filterTable]…)
Or
ADDMISSINGITEMS(<showAllColumn>[, <showAllColumn>]…, <table>,
<groupingColumn>[, <groupingColumn>]…[, filterTable]…)
It then covers the following parameters:
1. Table, or a table that contains items with the NON EMPTY function;
2. showAllColumn, or a column where items could be returned with no data
for the measures that you have already used;
3. filterTable, or a table that allows you to add logic to the equation, or to add
combinations of items without any data;
4. isSubtotal_columnName, or a Boolean column that has the IsSubtotal value,
and;
5. groupingColumn, or when argument is supplied by a group that used this
function.
At times, you can also use ROLLUPGROUP function, but you have to take note
of the following restrictions:
1. If you’re going to use the function with ROLLUPISSUBTOTAL, you’ll only
get one IsSubtotal column returned, and this should then be supplied per
ROLLUPGROUP.
2. If the supplied table argument is going to be defined, you can expect that
each column would correspond to each group of columns that you have, and
that names should be matched with Boolean characters.
3. You have to use this within the same arguments, as well.
This means that you could also use the following codes:
VAR 'RowHeadersShowAll' =
'RowHeadersInCrossTab',
'RowHeaders'
ROLLUPISSUBTOTAL
ROLLUPGROUP
CALCULATETABLE
ADDMISSINGITEMS
[Subtotal for Sales Territory Region]
[Subtotal for Sales Territory Country],
[Sales Territory Region],
[Sales Territory Region],
[Sales Territory Group],
[Sales Territory Country],
[Sales Territory Country]
VAR 'RowHeadersShowAll' =
'RowHeadersInCrossTab',
'RowHeaders'
ROLLUPISSUBTOTAL
'DateFilter','TerritoryFilter'
CALCULATETABLE
ADDMISSINGITEMS
[Subtotal for Sales Territory Region]
[Subtotal for Sales Territory Group],
[Subtotal for Sales Territory Country],
[Sales Territory Region],
[Sales Territory Region],
[Sales Territory Group],
[Sales Territory Country],
[Sales Territory Country]
All Selected Function
When you have certain context filters in columns and rows that you want to be
removed, the All Selected Function would certainly work great for you. This
involves explicit filters, as well, since it sees that the said elements are used
for query.
With the help of this function, all columns and rows would be duly
represented, together with other contents and explicit filters. It uses this syntax
below:
ALLSELECTED([<tableName> | <columnName>])
The AllSelected Function takes either one, or more arguments, and each
argument could either be columnName or tableName, and is different from the
ALL function, because it returns both column and context filters.
It involves the following parameters:
1. columnName, or the name of a DAX existing column, and;
2. tableName, or an existing table under the DAX syntax. Take note that you
could never take this parameter as an expression at all costs.
You can try this out by coding what’s shown below:
This will then give you the following results:
1. Reseller Visual for All of Calendar Year. This is the total value for all
your product sales across the year.
2. Reseller Sales Amount. This is the actual value of sales for the given
product category and year, and appears in the cell center of given reports.
3. Reseller Visual Total. This is the total value for all product categories and
years, and this usually appears on the rightmost corner of a given table.
4. Reseller Visual Total for all Product Category Name. This is the yearly
value for all product categories, and appears at the end of a row or column,
and across all product categories in the report.
5. Reseller Grand Total. This is basically the grand total of all reseller
sales.
Calculate Function
The Calculate Function is able to help you calculate an expression whose
context is modified by filters that you have just specified. It uses the following
syntax:
CALCULATE(<expression>,<filter1>,<filter2>…)
The value that it returns is basically the result of the expression, and it covers
the following parameters:
1. Expression, or the expression that needs to be evaluated, and;
2. Filters, which should be separated by commas (filter 1, filter 2, etc.) to
serve as Boolean Expressions.
You have to take note, though, that you cannot use the given expression as a
measure, and that it could not be nested in a calculated manner, and cannot be
used in any function without the presence of a table.
If you have not filtered the data, you can expect that the CALCULATE function
would really change, and the expression will be evaluated by means of context.
Any existing filters that you are using will have to be removed, too.
All Reseller Column Labels
Sales
Row Labels Clothes MakeUp Shoes
2016 30% 70% 50%
2015 20% 30% 50%
Grand Total 50% 100% 100%

To get the result above, you have to use the codes below:
=( SUM('ResellerSales_USD'[SalesAmount_USD]))
/CALCULATE( SUM('ResellerSales_USD'[SalesAmount_USD])
,ALL('ResellerSales_USD'))
You can also try doing this:

[Sales Red or Contoso - ALL columns filter] :=


CALCULATE (
[Sales Amount],
FILTER (
ALL ( 'Product'[Color], 'Product'[Brand] ),
'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"
[Sales Red or Contoso - CROSSJOIN columns filter] :=
CALCULATE (
[Sales Amount],
FILTER (
CROSSJOIN (
ALL ( 'Product'[Color] ),
ALL ( 'Product'[Brand] )
),
'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"
[Sales Red or Contoso - ALL KEEPFILTERS] :=
CALCULATE (
[Sales Amount],
KEEPFILTERS (
FILTER (
ALL ( 'Product'[Color], 'Product'[Brand] ),
'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"
[Sales Red or Contoso - CROSSJOIN KEEPFILTERS] :=
CALCULATE (
[Sales Amount],
KEEPFILTERS (
FILTER (
CROSSJOIN (
ALL ( 'Product'[Color] ),
ALL ( 'Product'[Brand] )
),
'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"
[Sales Red or Contoso - SUMMARIZE filter] :=
CALCULATE (
[Sales Amount],
FILTER (
SUMMARIZE (
'Product',
'Product'[Color],
'Product'[Brand]
),
'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"
CrossFilter Function
This helps you specify the cross-filtering direction of relationships when you
need some calculation to be done. It uses the following syntax:
CROSSFILTER(<columnName1>, <columnName2>, <direction>)
It covers the following parameters:
1. Direction, which is basically the cross-filter direction that has to be used.
This could either be One, Both, or None;
2. ColumnName 2, this is the name of an already existing column that is fully
qualified and uses the DAX Standard, especially if the arguments are given
in reverse position.
3. ColumnName 1, this is the name of another existing column, possibly your
first.
You should also take note of the following restrictions:
1. You can only use CROSSFILTER in instances when the filter is deemed to
be an argument.
2. If you’re dealing with a 1:1 relationship, take note that there should be no
difference between the “one” and “both” direction.
3. If you have set the relationship to be filtered once, you can expect that the
cross-filtering setting may not be important anymore.
4. If you are dealing with nested CALCULATE elements, and it already
contains a CrossFilter function, you can expect the innermost filter to
prevail in case of ambiguity or conflict.
5. If the columns are named as arguments, you can expect that error will be
returned.
So, for example, if you have the following image below, and you’d use
crossfilter:
https://i-msdn.sec.s-msft.com/dynimg/IC840340.jpeg

Then, you’d get a result that will look like the one below:

https://i-msdn.sec.s-msft.com/dynimg/IC840341.jpeg
Earlier Function
Meanwhile, the Earlier Function is used so that a specified column’s current
value could be returned, and is mostly used for Nested Calculations. If you
want to produce something good by means of inputting certain values so that
you could calculate from the table you have at hand.
It uses the following syntax:
EARLIER(<column>, <number>)
The return value of this is basically the current value of the number, as well as
the column, except for the descriptions of errors. It also involves the following
parameters:
1. Num. This is another positive number that is needed to pass outer
evaluation, and;
2. Column. This is an expression or column that’s able to have columns
resolved.
Therefore, if you’d use the following code:
= COUNTROWS(FILTER(ProductSubcategory,
EARLIER(ProductSubcategory[TotalSubcategorySales])
<ProductSubcategory[TotalSubcategorySales]))+1
You’d be able to work on a table such as the one below:
Product English Product Total Subcategory Subcategory
Subcategory Key Subcategory Sales Ranking
Name
37 Tires and Tubes $224,832.81 13
36 Pumps $12,695.18 34
35 Panniers 36
34 Locks $15,059.47 33
33 Lights 36
32 Hydration Packs $96,893.78 20
31 Helmets $451,192.31 9
30 Fenders $41,974.10 29
29 Cleaners $16,882.62 32
28 Bottles and Cages $59,342.43 24
27 Bike Stands $35,628.69 30
26 Bike Racks $220,720.70 14
25 Vests $240,990.04 11
24 Tights $189,179.37 16
23 Socks $28,337.85 31
22 Shorts $385,707.80 10
21 Jerseys $699,429.78 7
20 Gloves $228,353.58 12
19 Caps $47,934.54 28
18 Bib-Shorts $156,167.88 18
17 Wheels $648,240.04 8
16 Touring Frames $1,545,344.02 6
15 Saddles $52,526.47 26
14 Road Frames $3,636,398.71 5
13 Pedals $140,422.20 19
12 Mountain Frames $4,511,170.68 4
11 Headsets $57,659.99 25
10 Forks $74,727.66 21
9 Derailleurs $64,965.33 22
8 Cranksets $191,522.09 15
7 Chains $8,847.08 35
6 Brakes $62,113.16 23
5 Bottom Brackets $48,643.47 27
4 Handlebars $163,257.06 17
3 Touring Bikes $13,334,864.18 3
2 Road Bikes $40,551,696.34 1
1 Mountain Bikes $34,305,864.29 2
Related Function
If you need to get some data from a related table, you might as well use the
Related Function. It uses the following syntax:
RELATED(<column>)
It works on columns in such a way that it gives you back the values that you
want to be retrieved. The returned value would then be a single value that has
some relation to the current row, because this function requires relationships to
exist between two tables.
This is also closely related to the LookUp function because once that’s done,
you can expect that all important values will be examined, and a good
relationship will be created between the two. This function also needs to make
use of a row context to make way for a table scanning function, so for example,
if you want to work on a table like the one shown below:
Row Labels Internet Sales Non USA Internet
Sales
United States $9,389,479.79
United Kingdom $5,057,076.55 $5,057,076.55
Grand Total $26,054,827.45 $16,665,347.67
Germany $2,775,195.60 $2,775,195.60
France $2,490,944.57 $2,490,944.57
Canada $1,343,109.10 $1,343,109.10
Australia $4,999,021.84 $4,999,021.84

You’ve got to code something like this:


FILTER('InternetSales_USD', 'InternetSales_USD'[SalesTerritoryKey]<>1 &&
RELATED('SalesTerritory'[SalesTerritoryCountry])<>"United
States")'InternetSales_USD'[SalesTerritoryKey]<>2 &&
'InternetSales_USD'[SalesTerritoryKey]<>5)
'InternetSales_USD'[SalesTerritoryKey]<>3 &&
'InternetSales_USD'[SalesTerritoryKey]<>4 &&
And then, to get a grand table like this one below:
Non USA Column
Internet Labels
Sales
Row Accessories Bikes Clothing Grand Total
Labels
2008 $228,159.45 $5,386,558.19 $102,675.04 $5,717,392.68
2007 $156,480.18 $5,640,106.05 $70,142.77 $5,866,729.00
2006 $3,554,744.04 $3,554,744.04
2005 $1,526,481.95 $1,526,481.95
Grand $384,639.63 $16,107,890.23 $172,817.81 $16,665,347.67
Total

You would have to code what’s shown below:


= SUMX(FILTER( 'InternetSales_USD'
, RELATED('SalesTerritory'[SalesTerritoryCountry])
<>"United States"
)
,'InternetSales_USD'[SalesAmount_USD])
Values Function
This is one of the most important functions around as it gives you back a one-
column table that’s able to get distinct values from specified columns, with
certain values returned, and duplicate values removed.
However, it may not be used to help you return the values into worksheets,
columns, or cells in order to use them as immediate functions. This uses the
given syntax below:
VALUES(<TableNameOrColumnName>)
It also uses the Table or Column parameter because it is where the used values
are supposed to be returned to. You have to take note that if you are going to
deal with a filtered context, the VALUES Function would be returned as
VALUES, and you’d get a list that contains only the given elements in what has
already been filtered.
There are also some cases where the results for this one would not be identical
with what’s going on with the DISTINCT button. To understand this mismatch,
you can take a look at the table below:
MyOrders table MySales table
June 2 June 2 sales
June 1 June 1 sales
(no other dates) June 3 sales

If a list of dates has been returned using the DISTINCT function, you can then
get the corresponding dates that you need from the PivotTable, but you can take
note that only two dates would be returned. In order for this to happen, you
have to make use of the following formula:
=COUNTROWS(VALUES('InternetSales_USD'[SalesOrderNumber]))
UserRelationship Function
This function denotes the relationship between users that have to be used in
specific calculations that exists between two columns. This does not have any
return value, but instead enables the relationship that has been indicated during
the calculation’s duration.
To make it work, you can try the following syntax:
=CALCULATE(SUM(InternetSales[SalesAmount]),
USERELATIONSHIP(InternetSales[ShippingDate], DateTime[Date]))
With this one, you need to keep the following guidelines in mind:
1. User Relationships already have to exist so that the UserRelationship
function would get to work.
2. You can only use this for functions that have arguments in filter form, and
these include: Calculate, Closing Balance Month, Opening Balance Year,
Total MTD, and Total QTD.
3. If you need to join tables A and B together with use of multiple
relationships, you have to indicate each of those relationships in the
UserRelationship Function.
4. An error would be returned if any of the columns show that the argument is
not actually part of the relationship.
5. You can have up to 10 UserRelationship functions nested, and you’d have a
deeper level of nesting for your expressions.
6. If you have nested CALCULATE expressions,
KeepFilters Function
With the help of this filter, you’ll get to modify exactly how you want the filters
to be applied using the CALCULATE function, or other times, Calculate
Tables. This makes use of the syntax below:
KEEPFILTERS(<expression>)
It involves the Expression Parameter, and can be used within the CALCULATE
context so that standard behavior could be overridden, and so other
expressions could easily be evaluated. Filters that are already existing on
columns should be considered as part of the argument already.
Filter arguments are, by default, used for evaluating certain expressions, as
well as to filter other arguments, so that behavior is modified the way you want
it to. Any existing filters would then be compared with other arguments, and
then intersections should be used to evaluate the expressions. Both sets of
arguments should also be applied so that the only the right filters would be
added.
For example, if you want to compute for the internet sales for Washington,
followed by Washington and Oregon combined, and then for both Washington
and British Columbia. To get the results you need, you’d have to code what’s
written below:
EVALUATE ROW(
CALCULATE('Internet Sales'[Internet Total Sales]
CALCULATE('Internet Sales'[Internet Total Sales]
|| 'Geography'[State Province Code]="OR"
|| 'Geography'[State Province Code]="OR"
|| 'Geography'[State Province Code]="OR"
|| 'Geography'[State Province Code]="BC"
|| 'Geography'[State Province Code]="BC"
|| 'Geography'[State Province Code]="BC"
,'Geography'[State Province Code]="WA"
, KEEPFILTERS('Geography'[State Province Code]="WA"
, 'Geography'[State Province Code]="WA"
, 'Geography'[State Province Code]="WA"
, 'Geography'[State Province Code]="WA"
, 'Geography'[State Province Code]="WA"
, 'Geography'[State Province Code]="WA"
, CALCULATE('Internet Sales'[Internet Total Sales]
, CALCULATE('Internet Sales'[Internet Total Sales]
, CALCULATE('Internet Sales'[Internet Total Sales]
, CALCULATE(
, CALCULATE(
, "$$ in WA and OR"
, "$$ in WA and OR ??"
, "$$ in WA and BC"
, "$$ in WA !!"
"$$ in WA"
Then, by doing so, you’d get the results below:
Column Value
[$$ in WA and OR] $ 3,638,239.88
[$$ in WA and OR ??] $ 3,638,239.88
[$$ in WA !!] $ 2,467,248.34
[$$ in WA] $ 2,467,248.34
[$$ in WA and BC] $ 4,422,588.44
Chapter 9 Logical Functions

Meanwhile, Logical Functions are around to help you make sure that
information is returned by means of using expressions that are contained in sets
or in the values themselves. For this, you have the following:
And Function
The And Function helps you check whether both arguments are true or not. If
one of them doesn’t turn out to be true, you can expect that the result you’ll be
getting back would be FALSE.
This uses the following syntax:
AND(<logical1>,<logical2>)
It uses the logical_1, logical_2 parameter, which are basically the values that
you’d want to test, and depending on the test, the results would either come out
to be true, or false.
Take note that only two arguments are accepted for this one, so if you want to
use it for multiple expressions, you’d have to keep in mind that you can just
create a series of calculations and use the AND operator (&&) so you could be
handed back one simple expression.
For example, if you’d code the following:
= IF( AND( SUM( 'InternetSales_USD'[SalesAmount_USD])
, "Internet Hit"
, CALCULATE(SUM('InternetSales_USD'[SalesAmount_USD]),
PREVIOUSYEAR('DateTime'[DateKey] ))
>CALCULATE(SUM('ResellerSales_USD'[SalesAmount_USD]),
PREVIOUSYEAR('DateTime'[DateKey] ))
>SUM('ResellerSales_USD'[SalesAmount_USD])
)
You’d get a table like the one below:

ND Column
function Labels
Row 2005 2006 2007 2008 Grand
Labels Total
Wheels
Vests
Touring
Frames
Touring
Bikes
Tires and Internet
Tubes Hit
Tights
Socks
Shorts
Saddles
Road
Frames
Road Bikes
Pumps
Pedals
Panniers
Mountain
Frames
Mountain
Bikes
Locks
Lights
Jerseys
Hydration
Packs
Helmets
Headsets
Handlebars
Gloves
Forks

Fenders Internet
Hit
Derailleurs
Cranksets
Cleaners
Chains
Caps
Brakes
Bottom
Brackets
Bottles and Internet
Cages Hit
Bike Internet
Stands Hit
Bike Racks
Bib-Shorts

Grand
Total

Another example would be:

CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
ALL ( Calendar ),
'Calendar'[Date] <= MAX ( 'Calendar'[Date] )
&& YEAR ( 'Calendar'[Date] ) = YEAR ( MAX ( 'Calendar'[Date] ) )
)
)
False Function
Meanwhile, the False Function could help you return the logical value of False
by using the following syntax:
FALSE ()
The return value of this would always be False, and could also be interpreted
as the logical value of False. So if you’re going to use this code below:
=IF(SUM('InternetSales_USD'[SalesAmount_USD]) >200000, TRUE(),
false())
True-False Column
Labels
Row Labels 2005 2006 2007 2008 Grand
Total
Grand Total TRUE TRUE TRUE TRUE FALSE TRUE
FALSE FALSE FALSE FALSE FALSE FALSE
Components FALSE FALSE FALSE FALSE FALSE FALSE
Clothing FALSE FALSE FALSE FALSE FALSE TRUE
Bikes TRUE TRUE TRUE TRUE FALSE TRUE
Accessories FALSE FALSE TRUE TRUE FALSE TRUE
Not Function
This helps you change a value from True to False or False to True by using the
syntax below:
NOT(<logical>)
Return Value for this one would always be True or False. For example, if you
want to retrieve some data from a calculated column, it’s best to keep in mind
that you have to check for orders so that you’d get to create another calculated
column by using the code below:
=NOT([CalculatedColumn1])
IF Function
The IF Function checks if you have met the argument given by the first
condition so that more than one value could be returned to you, and then you
could get another value if the expression has been proven to be False.
This uses the following syntax:
IF(logical_test>,<value_if_true>, value_if_false)
Return Value could be any kind given by the expression, covering the following
parameters:
1. Value_if_true, or the kind of value that will be returned once the test has
been proven to be true;
2. Logical_test, or an expression or value that can be evaluated by True or
False, and;
3. Value_if_false, or the value that would be returned once the expression is
deemed to be False.
If you omit this when it is needed, the program would see your empty string as
(“”) so you have to make sure that you have this referenced, at best. You can try
it out by following what’s written below:
=IF([Calls]<200,"low",IF([Calls]<300,"medium","high"))
=IF([StateProvinceCode]= "CA" && ([MaritalStatus] = "M" ||
[NumberChildrenAtHome] >1),[City])
IFError Function
This right here could help you evaluate an expression, and see if it returns an
error—oir if it’ll give you back the value of the expression itself.
For this, you’d have to use the following syntax:
IFERROR(value, value_if_error)
It also covers the following parameters:
1. Value_if, which talks about any kind of value or expression, and;
2. Value_if_error, which is also about any kind of value or expression.
Return Value for this one would be the same type of scalar value. The function
is mostly used when you have already used the IF Function, and are getting the
same Error Messages, but with a couple of arguments taken out from them.
Values for A and B should always be the same data type.
To make this work, simply follow the codes written below:
IFERROR(A,B) := IF(ISERROR(A), B, A)
=IFERROR(25/0,9999)
True Function
Basically, this just returns the value of “True” and uses the following syntax:
TRUE ()
Return Value for this one is always True. True is then interpreted as its own
logical value, as well. To try to make it work, simply follow the following
code below:
= IF(SUM('InternetSales_USD'[SalesAmount_USD]) >200000, TRUE(),
false())
And then you’ll get the following result:
True-False Column
Labels
Accessories FALSE FALSE TRUE TRUE FALSE TRUE
Bikes TRUE TRUE TRUE TRUE FALSE TRUE
Clothing FALSE FALSE FALSE FALSE FALSE TRUE
Components FALSE FALSE FALSE FALSE FALSE FALSE
FALSE FALSE FALSE FALSE FALSE FALSE
Grand Total TRUE TRUE TRUE TRUE FALSE TRUE
Switch Function
If you have to evaluate certain expressions that could be found against a value
list, you’d be able to use this function to give you possible results in multiple
types.
For this, you have to use the following syntax:
SWITCH(<expression>, <value>, <result>[, <value>, <result>]…[,
<else>])
The return value for this one could be a scalar value coming from the
expressions you are trying to use. If the value gets to have a match, it means
that there’s no match with the other value you’ve used earlier, it means that no
real match has been found.
To compute for this one—together with months of the year, and the new
customers that you have, you can try following the codes below:
VALUES ( 'Date'[FullDate] ),
VALUES ( 'Date'[FullDate] ),
SUMMARIZE (
Sales[CustomerKey],
MEASURE Sales[NewCustomers] =
FILTER (
FILTER (
EVALUATE
DEFINE
'Date'[FullDate],
COUNTROWS (
CONTAINS (
CALCULATETABLE ( Sales, ALL ( 'Date' ) ),
ADDCOLUMNS (
=SWITCH([Month], 1, "January", 2, "February", 3, "March", 4, "April"
[DateOfFirstBuy]
, 9, "September", 10, "October", 11, "November", 12, "December"
, 5, "May", 6, "June", 7, "July", 8, "August"
, "Unknown month number" )
"DateOfFirstBuy", MIN ( Sales[OrderDate] )
"CountOfNewCustomers", [NewCustomers]
[CountOfNewCustomers] > 0
)
ORDER BY 'Date'[FullDate]
Or Function
This is another well-used function because it can change values from true to
false, and then false to true, and uses the NOT (<logical>) syntax.
Return Value for this one would either be True or False, which is especially
important if you are trying to retrieve data from certain columns. To test this
one, you can try coding what you see below:
IF( OR( CALCULATE(SUM('ResellerSales_USD'[SalesAmount_USD]),
'ProductSubcategory'[ProductSubcategoryName]="Touring Bikes") >
1000000
, CALCULATE(SUM('ResellerSales_USD'[SalesAmount_USD]),
'DateTime'[CalendarYear]=2016) > 2500000
)
, "Circle of Excellence"
By doing so, you’d get a result like the one you see below:
SalesPersonFlag True
OR function Column
Labels
Row Labels 2016 2015 2014 2013 Grand
Total
Bones, Susan
Chang, Cho
Edgecombe,
Marietta
Flinch-Fletchey, Circle of Circle of Circle of Circle of Circle of
Justin Excellence Excellence Excellence Excellence Excellence
Granger,
Hermione
Hagrid, Rubeus
Lestrange,
Rodolphus
Longbottom, Circle of Circle of Circle of Circle of Circle of
Neville Excellence Excellence Excellence Excellence Excellence
Malfoy, Draco

Patil, Padma
Patil, Parvati Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Potter, Harry
Warren, Myrtle
Weasley, Fred Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Weasley, George
Weasley, Ronald Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Wood, Oliver
Grand Total Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Chapter 10: Text Functions
Blank Function
This generally just gives you back the “Blank” result. It uses the syntax below:
BLANK ()
The return value for this one is “blank”. What you can keep in mind is that
blanks and nulls are not necessarily the same thing, and that DAX treats blanks
differently from how they were used in Excel. You can use blanks by following
this syntax:
=IF( SUM(InternetSales_USD[SalesAmount_USD])= 0 , BLANK() ,
SUM(ResellerSales_USD[SalesAmount_USD])/SUM(InternetSales_USD[SalesAmount_U
)
To try it out, just follow the codes below:
=IF( SUM(InternetSales_USD[SalesAmount_USD])= 0 , BLANK() ,
SUM(ResellerSales_USD[SalesAmount_USD])/SUM(InternetSales_USD[SalesAmount_U
)
WHERE
SELECT
LEFT OUTER JOIN [Product] ON [Sales].[ProductKey]= [Product].
[ProductKey]
LEFT OUTER JOIN [Product] ON [Sales].[ProductKey]= [Product].
[ProductKey]
LEFT OUTER JOIN [Date].[OrderDateKey]=[Date].[DateKey];
LEFT OUTER JOIN [Date] ON [Sales].[OrderDateKey]=[Date].[DateKey]
LEFT OUTER JOIN [Date] ON [Sales].[OrderDateKey]=[Date].
[DateKey]
FROM [Sales]
FROM [Sales]
FROM [Sales]
[Product].[Unit Cost] = 1;
[Product].$ROWFILTER IN '0xfff…';
[Date].[Calendar Year], SUM([Sales].[Quantity] * [Sales].[Unit Price])
AS [$Measure0]
[Date].[Calendar Year], SUM([Sales].[Quantity] * [Sales].[Unit Price])
AS [$Measure0]
[Date].[Calendar Year], SUM([Sales].[Quantity] * [Sales].[Unit Price])
AS [$Measure0]
Doing so would also help you open MySQL, which will make whatever it is
that you are working on more manageable.
Pre-Defined Numeric Format Function
These are numeric format names that have already been predefined for, and
which you can use to sort out your data. Look at the table below to understand
what this is about:
Specification of Format Description
Currency For currency, what would be
displayed are numbers with different
operators, with two digits to the right
of the decimal operator. System
Locale Settings would then determine
the output.
General Number For this one, numbers would be
displayed with no thousand operators
Standard This displays numbers with thousands
of operators
Fixed This helps you display one digit to
the left, and two digits to the right of
the operator
Percent For this one, numbers multiplied by
100 will be displayed with the
percent sign (%) automatically
appended to the right
Yes/No If the number is 0, “No” will be
displayed. If not, it would
automatically display “Yes”
On/Off If the number is 0, “Off” will be
displayed. If not, it will display
“Yes”
True/False If the number is 0, False will be
displayed. If not, it will display True.
Scientific This uses standard scientific notation,
with two significant digits provided
for your benefit.
For this one, you can try coding the following:
FORMAT( 12345.67, "General Number")
FORMAT( 12345.67, "Currency")
FORMAT( 12345.67, "Fixed")
FORMAT( 12345.67, "Standard")
FORMAT( 12345.67, "Percent")
FORMAT( 12345.67, "Scientific")
Pre-Defined Date and Time Format Function
As for this one, you’d get pre-define date and time format names, and if other
strings would be used, as opposed to this one, you would then get a specified
date and time format. Check the table below to see what you can use:
Specification of Format Description
“Long Date”/ “Medium Date” A date will be displayed depending
on your current culture’s date and
time format (i.e., June 26, 2016)
“General Date” This displays a current time and date,
and could be determined by the
current culture value of the
application
“Long time” or Based on your current culture’s long
time format, you’ll get something like
12:07:31 AM displayed onscreen
“Short Date” Depending on your current short time
format, a date would be displayed for
you here. A good example would be
01/25/16.
“Short Time” This displays time in a 24 hour
format
“Medium Time” This displays time in a 12-hour
format

However, you need to keep in mind that if the value is Blank, you just might get
an empty string, and the value would be formatted using the “General Date”
format.
Custom Numeric Formats Function
This one is about a user-defined numeric expression that are divided in 3
sections for the numbers, and should be separated by semi-colons. You’d
notice that only 1 section will be allowed if it contains one or more of the
predefined functions. For this, you have the following format specifications:
Specifications of Formats Description
None Number would be displayed without
any form of formatting
# This is a placeholder for the digits
you have onhand, otherwise, a digit
would not be displayed at all. It
works like 0 because as a
placeholder, it has fewer digits than
characters on either side of the
decimal separators.
0 (Zero Character) This acts as a placeholder for digits,
and could display either Zero or a
digit. If digits have fewer zeros than
are displayed, the zeros will be
moved to the right of the decimal
separators, and when there are too
much, they will be moved to the left
—without any other modification.
% This is the percentage placeholder
which could help you multiply
numbers by 100, and should be
inserted by how it looks like in the
format string.
. (Dot character) This is a decimal placeholder which
determines the number of digits that
should be displayed in the left and
right sides of the decimal operator. If
zero is around, it should then be used
as the placeholder.
, (comma character) The comma acts as the separator for
thousands, which can separate
thousands from hundreds, and could
be specified by surrounding it with
digital placeholders, such as # or 0.

For the other positions, multiple


operators prove to be helpful, and
could be treated by specifying the
thousands operators, and could even
be used as hundred operators in some
locales.
/ (forward slash operator) This is mostly used as a date
separator, with other characters being
able to represent time separators.
Day, month, and year are separated
by this one, and it’s up to your system
to decide how it wants the date to
show up onscreen.
: (colon operator) This is a time separator which could
separate seconds, hours, and minutes,
and where time values could be
formatted. Your system would also
determine the final output, as with the
date separator.
-+$() These are literal characters, which
means that they should be displayed
as they are in the format strings. They
could be preceded by a blacklash ()
or could be enclosed in quotation
marks (“”)
E-, E+, e-, e+ This denotes a scientific format of
writing, which means that at least one
placeholder is in the scientific
format, and has to be inserted
between the number and its exponent.
The ones with negative signs should
be for negative exponents, and the
ones with positive signs should be for
the positive exponents.
“ABC” If you have double quotation marks,
the strings inside those would be
displayed with the help of ABC. Text
should then be enclosed within
Chr(34) for it to be left inside the
quotation mark.
** or \\ (backward slash character) This will have the next character of
the string displayed for you to see.
Any special character should always
be preceded by a backslash

To see what this means, just check out the data below:
Format (Style) "5" "-5" "0.5" "0"
formatted formatted formatted formatted
as as as as
Zero-length 5 -5 0.5 0
string ("")
0 5 -5 1 0
0.00 5.00 -5.00 0.50 0.00
#,##0 5 -5 1 0
$#,##0;($#,##0) $5 ($5) $1 $0
$#,##0.00; $5.00 ($5.00) $0.50 $0.00
($#,##0.00)
0% 500% -500% 50% 0%
0.00% 500.00% -500.00% 50.00% 0.00%
0.00E+00 5.00E+00 -5.00E+00 5.00E-01 0.00E+00
0.00E-00 5.00E00 -5.00E00 5.00E-01 0.00E00
"$#,##0;;\Z\e\r\o" $5 $-5 $1 Zero
Custom Date and Time Format Function

You could also create custom date and time formats for your system, and for
that, you can use the table below as reference:
Specifications of Format Description
(/) This is mostly used as a date
separator, with other characters being
able to represent time separators.
Day, month, and year are separated
by this one, and it’s up to your system
to decide how it wants the date to
show up onscreen.
(:) This is a time separator which could
separate seconds, hours, and minutes,
and where time values could be
formatted. Your system would also
determine the final output, as with the
date separator
d This displays the day as a number
without zeros preceding it. However,
you should use % if the said day is
the only different character in your
user-defined numeric format
(%) This means that a certain character
should be read as a single letter
format, without much regard to other
letters trailing it, and could also
indicate that the said character is part
of a user-defined format.
dd This displays the date as a number
with zero preceding it (01, 02, etc)
ddd This means that the day has been
abbreviated (i.e., Mon, Tue, Wed,
etc)
dddd This displays the name of the day in
full (i.e., Sunday, Thursday, etc)
M This displays the month as a number
without any leading zeros (1, 2, 3…)
MM Displays the month as a number with
a preceding zero (01, 02…)
MMM This means that the month has been
abbreviated (Jan, Feb)
MMMM Displays the month in full (January,
February)
H Displays the hour as a number
without any preceding zeros by using
the 12-hr clock.
Gg Displays the era or period string
(AD, BC)
Hh Displays the hour as a number
involving leading zeros (03, 05)
Mm Displays minute as a number with
leading zeros
M Displays minute as a number without
leading zeros
S Displays seconds without any
preceding zeros
Ss Displays the second number with
leading zeros
T Uses the 12-hr clock in uppercase
dimensions
F Displays fractions of seconds
Tt Displays an uppercase AM clock
Y Displays year without any preceding
zeros
Yy Displays the year in 2-digit numeric
formats
Yyy Displays year in 4-digit numeric
format
Yyyy Displays year in full
Zz Displays timezone offsets with
leading zeros
Z Displays timezone offset without
leading zeros
Zzz Displays full timezone offset
Code Function
This will give you back a numeric code for the text string’s first given
character and works either in ANSI for Windows, or Macintosh Character Set
for MAC. Text is the main code here, and it will just give you back the return
value of the first number of the string.
So, for example, the code below would give you numeric characters based on
what you have coded.
VAR 'RowHeadersShowAll' =
'RowHeadersInCrossTab',
'RowHeaders'
ROLLUPISSUBTOTAL
ROLLUPGROUP
CALCULATETABLE
ADDMISSINGITEMS
[Subtotal for Sales Territory Region]
[Subtotal for Sales Territory Country],
[Sales Territory Region],
[Sales Territory Region],
[Sales Territory Group],
[Sales Territory Country],
[Sales Territory Country]
VAR 'RowHeadersShowAll' =
'RowHeadersInCrossTab',
'RowHeaders'
ROLLUPISSUBTOTAL
'DateFilter','TerritoryFilter'
CALCULATETABLE
ADDMISSINGITEMS
[Subtotal for Sales Territory Region]
[Subtotal for Sales Territory Group],
[Subtotal for Sales Territory Country],
[Sales Territory Region],
[Sales Territory Region],
[Sales Territory Group],
[Sales Territory Country],
[Sales Territory Country]
Find Function
As the name suggests, this will definitely help you find something that you’re
looking for in a text string. It uses the following syntax:
FIND(<find_text>, <within_text>[, [<start_num>][, <NotFoundValue>]])
This covers the following parameters:
1. Find_text, or simply the text that you want to find. This also means that
you’d have to use double quotes so that the first character could be matched
using wildcard characters, such as * or ? so you’d be able to find exactly
what you want.
2. Start_num, this one is pretty much optional because it’s simply the character
where you want the search to begin.
3. Within_text, which is the place where you’d want to find the character.
4. NotFoundValue, which is also optional because it is where the value that
should be returned has to be found, and could either be blank, zero, or
negative 1.
Excel actually has multiple versions of this, but it’s best and more accurate to
stay with the DAX version, especially if you’re working on Power Pivot. DAX
could accommodate single-byte, and double-byte characters—something Excel
is not very good at.
To test, check this code:
= IF( AND( SUM( 'InternetSales_USD'[SalesAmount_USD])
, "Internet Hit"
, CALCULATE(SUM('InternetSales_USD'[SalesAmount_USD]),
PREVIOUSYEAR('DateTime'[DateKey] ))
>CALCULATE(SUM('ResellerSales_USD'[SalesAmount_USD]),
PREVIOUSYEAR('DateTime'[DateKey] ))
>SUM('ResellerSales_USD'[SalesAmount_USD])
)
Then, type:
FIND(<find_Internet Hit>, <within_second line>[, [<start_num>][,
<NotFoundValue>]])
And then see what happens!
Chapter 11 Parent Child Function

This function is basically about having parent and child pages, or in layman’s
terms, main pages, and their sub-pages. For this one, you can make use of the
following:
Path Function
This one would give you back a limited text string that contains both parent and
child identifiers. It uses the syntax:
PATH(<ID_columnName>, <parent_columnName>)
The return value for this one would always be a delimited text that contains
parent and current identifiers. It also covers the following parameters:
1. Parent_columnName, which is the name of a column that’s already existing,
and which contains the parent page’s identifiers, and;
2. ID_columnName, which is the name of an already existing column.
For this, you can also code something like this:
=PATH(Employee[EmployeeKey], Employee[ParentEmployeeKey])
This means that:
1. Values in both column names should be under the same data types.
2. “|” or a vertical bar should act as the ascendant separator, or delimiter, in
other words.
3. If you have BLANK as the parent_columnName, you’d expect that the
ID_columnName that would be returned would be Path (), otherwise, you’d
get a column with no data in it.
4. If BLANK is the ID_columnName, then Path() would be returned as
BLANK, as well.
5. If “|” or vertical bar is used for the ID_columnName, Path() would turn out
to be an error.
Path Item Function
If you want a certain returned to you in a specified position, then, you can make
use of the Path Item Function (PathItem Function), and positions should then be
counted from left to right. It uses the following syntax:
PATHITEM(<path>, <position>[, <type>])
This uses the following parameters:
1. Position, or an integer that is about the position of the item that’s supposed
to be returned;
2. Path, or a text string of a PATH Function in the form of results, and;
3. Type, or a data type enumeration.
The return value for this one would always be identified at the end of the given
identifiers. It could then be used to return specific hierarchy levels, and
specific positions that are greater than 1. If deemed that what you’re using is
not a valid element, you can expect that, you’d get an error in return. Take a
look at the example below so you’d have a better idea of what this is about:
Enumeration Alternate Enumeration Description
INTEGER 1 Results are returned as
integers.
TEXT 0 Results are returned
with the data type text.
(default).
PathLength Function
This gives you back the exact number of “parents” for a specific path, and the
return value for this one would be the number of items given by the specified
item in a certain path, including the item that was already specified earlier.
You can simply test this out by typing:
=PATHLENGTH(PATH(Employee[EmployeeKey],
Employee[ParentEmployeeKey]))
Chapter 12 Statistical Functions

Of course, there are also statistical functions that help you create various
aggregations, such as counts, averages, sums, and the like. For this, you have
the following:
CrossJoin Function
This function gives you back a Cartesian Product that contains all the tables
and rows from the arguments. It uses the following syntax:
CROSSJOIN(<table>, <table>[, <table>]…)
The return value from this one would be all of the tables and rows in the
argument. One thing you have to remember is that table arguments from the
columns have to be different from, and the total number of rows that you’d get
would be equal to the number of rows that you already have.
Here are some good examples:
CROSSJOIN( Colors, Stationery)

Blue Crosshatch serif embossed


Blue Crosshatch sans-serif engraved
Green Vertical Stripe serif embossed
Green Vertical Stripe sans-serif engraved
Red Horizontal Stripe serif embossed
Red Horizontal Stripe sans-serif engraved

Font Presentation
sans-serif engraved
serif embossed

Color Pattern
Blue Crosshatch
Green Vertical Stripe
Red Horizontal Stripe
Generate Function
This is quite a useful function that gives you a Cartesian Product between each
of the rows in Table 1, together with results that have been evaluated from the
second table. Ir uses the following syntax:
GENERATE(<table1>, <table2>)
It covers the following parameters:
1. Table1, or a DAX expression that’ll send you back a table, or;
2. Table2, another DAX expression that will bring you back another table.
If an empty table is returned by the current table1 row, then it means that the
result should not contain any rows from the first table, but should not be
coherent with GENERATEALL. If there are no different names, you can expect
that an error would be returned.
To test it out, you can try coding what’s written below:
GENERATE(
,SUMMARIZE(ProductCategory
, [ProductCategoryName]
, "Reseller Sales", SUMX(RELATEDTABLE(ResellerSales_USD),
ResellerSales_USD[SalesAmount_USD])
SUMMARIZE(SalesTerritory, SalesTerritory[SalesTerritoryGroup])
)
For this, you’d see that one table would be about territory groups, while the
other would be about product categories, as shown on the table below:
ProductCategory[ProductCategoryName]
SalesTerritory[SalesTerritoryGroup]
Pacific Accessories
Pacific Bikes
Pacific Clothing
Pacific Components
North America Accessories
North America Bikes

North America Clothing

North America Components

Europe Accessories
Europe Bikes

Europe Clothing
Europe Components
DataTable Function
If you want to declare an inline set of values, you need this function to help you
out with.
It uses the given syntax below:
DATATABLE (ColumnName1, DataType1, ColumnName2, DataType2...,
{{Value1, Value2...}, {ValueN, ValueN+1...}...})
Inline Values are the return value for this one, and it covers the following
parameters:
1. Value, or a single argument. You could create one by using the Excel
Syntax, and you should have the results nested along arrays.
2. DataType, or an enumeration encompassing DOUBLE, INTEGER,
STRING, BOOLEAN, DATETIME, and CURRENCY.
3. ColumnName, or any form of DAX expression that could send you back a
table.
For this, you can try coding what’s written below:
=DataTable("Name", STRING,
"Region", STRING
,{
{" User4","West"},
{" User4","East"}
{" User3","West"},
{" User2","East"},
{" User1","East"},
}
)
Count Function
This just helps you count the number of cells that you have in one column that
has numbers in it, and it also uses the following syntax:
COUNT(<column>)
The return value for this one is a whole number, and the column is the sole
argument allowed for this. If text found in those columns can’t be translated as
numbers, chances are, they would not be translated at all, and would not be
counted, as well.
Average Function
This shows you the columns where you want to get averages from, which is
also known as the arithmetic mean. It uses the following syntax:
AVERAGE(<column>)
Return Value for this one would be a decimal that would then represent the
average of the numbers that you are dealing with. You can try coding by
following what’s written below:
=AVERAGE(InternetSales[ExtendedSalesAmount])
For this, you have to remember that:
1. Empty cells will have to be ignored, and not taken as logical values.
2. Aggregation cannot be performed if text is not contained in any of the
columns.
3. Keep in mind that the difference between empty cells should contain a 0
(zero) value if you want to average them.
Summarize Columns Function
It’s hard to understand every data that you have if you see them as a whole—or
one long list of everything involved in your program. That would be ultimately
confusing, and detrimental to the success of your program. Therefore, it would
be helpful if you could summarize things out.
This uses the following syntax:
SUMMARIZECOLUMNS( <groupBy_columnName> [, <
groupBy_columnName >]…, [<filterTable>]…[, <name>, <expression>]
…)
Return Value for this one is a combination of values from the columns that have
already been supplied, based on the kind of grouping that has been specified
earlier. It covers the following parameters:
1. Expression, or any DAX Expression that could bring you back a single
value;
2. Name, or a string that represents a column name that should be used for
subsequent expressions;
3. filterTable, or an expression that shows that certain tables have to be
filtered or modified, and;
4. groupby_ColumnName, or fully developed column references (Table |
Column) so that distinct values could be added to the base tables.
Take note that this does not guarantee any defined order for your results, but
could definitely keep things more manageable for you. A column also could not
be specified more than once, or else, the formula would be deemed invalid.
So, for example, you have the table below:
CustomerId TotalQty BlankIfTotalQtyIsNot3
C 3 3
B 3 3
A 5

And then, say, you want one of those elements to be ignored, what you’d have
to do is follow the codes below:
SUMMARIZECOLUMNS( Sales[CustomerId], "Total Qty", IGNORE( SUM(
Sales[Qty] ) ), “BlankIfTotalQtyIsNot3”, IF( SUM( Sales[Qty] )=3, 3 ) )
After doing so, you’d get the result shown below:
CustomerId TotalQty BlankIfTotalQtyIsNot3
C 3 3
B 3 3

You can also do rollups and single subtotals by doing the following:
SUMMARIZECOUMNS (Regions[State], ROLLUPADDISSUBTOTAL (
Sales[CustomerId], “IsCustomerSubtotal” ), Sales[Date], "Total Qty",

SUM( Sales[Qty] )) ROLLUPADDISSUBTOTAL ( <groupBy_columnName>,


<isSubtotal_columnName>[, <groupBy_columnName >,
<isSubtotal_columnName>…] )
Upon doing so, the result will be something like this:

CustomerID IsCustomerSubtotal State Total Date IsDateSubtotal


Qty
C FALSE OR 2 7/10/2014
C FALSE OR 1 7/11/2014
C FALSE OR 3 TRUE
B FALSE WA 1 7/10/2014
B FALSE WA 2 7/11/2014
B FALSE WA 3 TRUE
A FALSE WA 5 7/10/2014
A FALSE WA 5 TRUE
TRUE WA 6 7/10/2014
TRUE WA 2 7/11/2014
TRUE OR 2 7/10/2014
TRUE OR 1 7/11/2014
TRUE WA 8 TRUE
TRUE OR 3 TRUE

Now, in order to get multiple subtotals, just copy the code below to get the
succeeding table as a result:
Multiple subtotals
SUMMARIZECOLUMNS( ROLLUPADDISSUBTOTAL( Sales[CustomerId],
"IsCustomerSubtotal" ),
ROLLUPADDISSUBTOTAL(ROLLUPGROUP(Regions[City],
Regions[State]), “IsCityStateSubtotal”),"Total Qty", SUM( Sales[Qty] ) )
State CustomerId IsCustomerSubtotal Total City IsCityStateSubtotal
Qty
A FALSE 5 FALSE
B FALSE 3 TRUE
C FALSE 3 TRUE
TRUE 11 TRUE
OR C FALSE 3 Portland FALSE
OR TRUE 3 Portland FALSE
WA A FALSE 2 Bellevue FALSE
WA B FALSE 2 Bellevue FALSE
WA A FALSE 3 Redmond FALSE
WA B FALSE 1 Redmond FALSE
WA TRUE 4 Bellevue FALSE
WA TRUE 4 Redmond FALSE
GroupBy Function
Sometimes, you have to group data into certain partitions just to determine
what each group is about, and what separates them from the rest. In a way, it
works like the Summarize Function, but the difference is that it does not
necessarily calculate data implicitly, but rather focuses on what are the
similarities of various groups.
This uses the syntax:
GROUPBY (<table>, [<groupBy_columnName1>], [<name>,
<expression>]… )
It covers the following parameters:
1. Expression, or any DAX Expression that could bring you back a single
value;
2. Name, or a string that represents a column name that should be used for
subsequent expressions;
3. filterTable, or an expression that shows that certain tables have to be
filtered or modified, and;
4. groupby_ColumnName, or fully developed column references (Table |
Column) so that distinct values could be added to the base tables.
You also have to remember that:
1. You should start with one specific table.
2. There’d be one row of results for each group, but rows have to be
represented in the original table, as well.
3. Use all of the groupBy columns so you could create “groupings”.
4. Evaluating extensions for each group is essential.
5. There has to be a corresponding expression for each column that you want
to be defined, and every group_columnName should be placed in a given
table.
6. A selected set of rows would be grouped by this function, especially if
you’re dealing with the CURRENTGROUP().
For this, you can try the following codes below:
GROUPBY (
VAR SalesByCountryAndCategory =
SalesByCountryAndCategory,
Sales,
Sales,
Product[Category],
Product[Category],
GROUPBY (
Geography[Country],
Geography[Country],
Geography[Country],
Evaluate GROUPBY (
DEFINE
“Total Sales”, SUMX( CURRENTGROUP(), Sales[Price] * Sales[Qty])
“Total Sales”, SUMX( CURRENTGROUP(), Sales[Price] * Sales[Qty])
“Max Sales”, MAXX( CURRENTGROUP(), [Total Sales])
)
GenerateAll Function
This gives you back a Cartesian Product that comes between each of the rows
from Table1, and could also be deemed as results from the second table. This
uses the following syntax:
GENERATEALL(<table1>, <table2>)
The return value for this one would be the Cartesian product that has been
mentioned earlier. It covers the following parameters:
1. Table1, or a DAX expression that’ll send you back a table, or;
2. Table2, another DAX expression that will bring you back another table.
3. If an empty table is returned by the current table1 row, then it means that the
result should not contain any rows from the first table, but should not be
coherent with GENERATEALL. If there are no different names, you can
expect that an error would be returned.
Let’s say you are dealing with a table like the one seen below:
ProductCategory[ProductCategoryName]
SalesTerritory[SalesTerritoryGroup]
Pacific Accessories
Pacific Bikes
Pacific Clothing
Pacific Components
North America Accessories
North America Bikes

North America Clothing

North America Components

NA Accessories
NA Bikes
NA Clothing
NA Components
Europe Accessories
Europe Bikes

Europe Clothing
Europe Components

To test it out, you can try coding what’s written below:


GENERATEALL(
SUMMARIZE(SalesTerritory, SalesTerritory[SalesTerritoryGroup])
,SUMMARIZE(ProductCategory
, [ProductCategoryName]
, "Reseller Sales", SUMX(RELATEDTABLE(ResellerSales_USD),
ResellerSales_USD[SalesAmount_USD])
)
)
GENERATEALL(
SUMMARIZE(SalesTerritory, SalesTerritory[SalesTerritoryGroup])
,SUMMARIZE(ProductCategory
, [ProductCategoryName]
, "Reseller Sales", SUMX(RELATEDTABLE(ResellerSales_USD),
ResellerSales_USD[SalesAmount_USD])
)
)
Upon doing so, you’d get the tables below as results:
SalesTerritory[SalesTerritoryGroup]
Pacific
North America
NA
Europe

You’d also get this one below:


ProductCategory[ProductCategoryName] [Reseller Sales]
Components $ 11,205,837.96
Clothing $ 1,669,943.27
Bikes $ 63,084,675.04
Accessories $ 534,301.99

You should keep in mind, though, that once you check the said tables and have
them evaluated, you’ll get the right results for each territory, too.
Arrange Function
This gives you back a Cartesian Product that comes between each of the rows
from Table1, and could also be deemed as results from the second table. This
uses the following syntax:
ARRANGEALL(<table1>, <table2>)
The return value for this one would be the Cartesian product that has been
mentioned earlier. It covers the following parameters:
1. Table1, or a DAX expression that’ll send you back a table, or;
2. Table2, another DAX expression that will bring you back another table.
3. If an empty table is returned by the current table1 row, then it means that the
result should not contain any rows from the first table, but should not be
coherent with GENERATEALL. If there are no different names, you can
expect that an error would be returned.
Let’s say you are dealing with a table like the one seen below:
SalesPersonFlag True
OR function Column
Labels
Row Labels 2016 2015 2014 2013 Grand
Total
Bones, Susan
Chang, Cho
Edgecombe,
Marietta
Flinch-Fletchey, Top Top Top Top Top Top
Justin honors honors honors honors honors honors
Granger,
Hermione
Hagrid, Rubeus
Lestrange,
Rodolphus
Longbottom, Top Top Top Top Top Top
Neville honors honors honors honors honors honors
Malfoy, Draco Top
honors
Patil, Padma
Patil, Parvati Top Top Top Top Top Top
honors honors honors honors honors honors
Potter, Harry
Warren, Myrtle
Weasley, Fred Top Top Top Top Top Top
honors honors honors honors honors honors
Weasley, George
Weasley, Ronald Top Top Top Top Top Top
honors honors honors honors honors honors
Wood, Oliver
Grand Total Top Top Top Top Top Top
honors honors honors honors honors honors

What you can do to arrange them in a way you want—such as, for example,
getting only names and rankings of the values inputted for 2016, what you can
do is follow the codes below:
ARRANGEALL(
SUMMARIZE(SalesTerritory, SalesTerritory[SalesTerritoryGroup])
,SUMMARIZE(ProductCategory
, [ProductCategoryName]
, "NAMES | TOP HONORS 2016",
SUMX(RELATEDTABLE(ResellerSales_USD),
ResellerSales_USD[SalesAmount_USD])
)
And then you’ll get something like what you see below:
SalesPersonFlag True
OR function Column
Labels
Row Labels 2016

Bones, Susan
Chang, Cho
Edgecombe,
Marietta
Flinch-Fletchey, Top
Justin honors
Granger,
Hermione
Hagrid, Rubeus
Lestrange,
Rodolphus
Longbottom, Top
Neville honors
Malfoy, Draco
Patil, Padma
Patil, Parvati Top
honors
Potter, Harry
Warren, Myrtle
Weasley, Fred Top
honors
Weasley, George
Weasley, Ronald Top
honors
Wood, Oliver
Grand Total Top
honors
Chapter 13 DAX Exercises and Puzzles

To test how much you have learned, try comprehending these DAX Exercises
and Puzzles below!
Data Lineage
Data Lineage means that your physical columns have to be coherent—or else,
it means that your formulas may be wrong, or there are certain errors that you
may have committed.
Going back to the parent and child functions, you have to make sure that if you
have mini tables, it would be easy for them to be referenced back to your main
table—or parent page. So, for example, you have this table below:

http://www.sqlbi.com/wp-content/uploads/DataLineage-Currency.png

Now, follow the code below:


CALCULATETABLE (
VALUES ( Currency[Currency Code] ),
VALUES ( Currency[Currency Code] ),
SELECTCOLUMNS (
FILTER (
Currency,
CROSSJOIN (
[another] <> Currency[Currency Code]
),
)
"Another", Currency[Currency Code]
)
Done? So, which among these did you get?
1. An empty table;
2. An error, or;
3. A table that has some currency rows in it?
Execute the query by downloading the sample file that you’d get, and then try
the codes below to see what you are going to get:
CALCULATETABLE (
Currency,
FILTER (
CROSSJOIN (
VALUES ( Currency[Currency Code] ),
SELECTCOLUMNS (
VALUES ( Currency[Currency Code] ),
"Another", Currency[Currency Code] & ""
)
),
[another] <> Currency[Currency Code]
)
)
This exercise is determined to help you understand more about data lineage, so
do be mindful of the results that you’ll see!
In Query Puzzle
In relation to data lineage, it would also be good to understand the In Query
Puzzle. Check the example below. It shows that you have a Sales Table, and
some loops thata re related to it in big ways.

http://www.sqlbi.com/wp-content/uploads/RELATED-and-Lineage-1-1.png

Now, follow the codes below:


EVALUATE
WhatWillBeTheResult =
SUMMARIZE (
SUMMARIZE (
SELECTCOLUMNS ( 'Product', "ProductColor", Product[Color] ),
SELECTCOLUMNS (
'Product',
ADDCOLUMNS (
ADDCOLUMNS (
[ProductColor]
[ProductColor]
[ProductCategory],
),
),
),
"TotalSales", CALCULATE ( SUM ( Sales[Quantity] ) )
"TotalSales", CALCULATE ( SUM ( Sales[Quantity] ) )
"ProductColor", Product[Color]
"ProductCategory", RELATED ( 'Product Category'[Category] ),
)
The question now is: what results did you get, and how do you think the
RELATED function can be seen in the columns that you have with you?
Many-to-Many Relationships
Suppose you’re dealing with the following tables:

CustomerID IsCustomerSubtotal State Total Date IsDateSubtotal


Qty
C FALSE OR 2 7/10/2014
C FALSE OR 1 7/11/2014
C FALSE OR 3 TRUE
B FALSE WA 1 7/10/2014
B FALSE WA 2 7/11/2014
B FALSE WA 3 TRUE
A FALSE WA 5 7/10/2014
A FALSE WA 5 TRUE
TRUE WA 6 7/10/2014
TRUE WA 2 7/11/2014
TRUE OR 2 7/10/2014
TRUE OR 1 7/11/2014
TRUE WA 8 TRUE
TRUE OR 3 TRUE

ND Column
function Labels
Row 2005 2006 2007 2008 Grand
Labels Total
Wheels
Vests
Touring
Frames
Touring
Bikes
Tires and Internet
Tubes Hit
Tights
Socks
Shorts
Saddles
Road
Frames
Road
Bikes
Pumps
Pedals
Panniers
Mountain
Frames

SalesPersonFlag True
OR function Column
Labels
Row Labels 2016 2015 2014 2013 Grand
Total
Bones, Susan
Chang, Cho
Edgecombe,
Marietta
Flinch-Fletchey, Circle of Circle of Circle of Circle of Circle of
Justin Excellence Excellence Excellence Excellence Excellence
Granger,
Hermione
Hagrid, Rubeus
Lestrange,
Rodolphus
Longbottom, Circle of Circle of Circle of Circle of Circle of
Neville Excellence Excellence Excellence Excellence Excellence
Malfoy, Draco

Patil, Padma
Patil, Parvati Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Potter, Harry
Warren, Myrtle
Weasley, Fred Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Weasley, George
Weasley, Ronald Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence
Wood, Oliver
Grand Total Circle of Circle of Circle of Circle of Circle of
Excellence Excellence Excellence Excellence Excellence

The question now is: how will you be able to create connections between
them, especially as there are lots of values involved now?
Well, the answer is that you’ve got to code what’s written below:
Balance M2M 2016:=
CALCULATE (
[Balance Last Date],
GENERATE(
,SUMMARIZE(ProductCategory
, [ProductCategoryName]
, you can try following the codes below:
VALUES ( 'Date'[FullDate] ),
VALUES ( 'Date'[FullDate] ),
SUMMARIZE (
Sales[CustomerKey],
MEASURE Sales[NewCustomers] =
FILTER (
FILTER (
EVALUATE
DEFINE
'Date'[FullDate],
COUNTROWS (
CONTAINS (
CALCULATETABLE ( Sales, ALL ( 'Date' ) ),
ADDCOLUMNS (
=SWITCH([Month], 1, "January", 2, "February", 3, "March", 4, "April"
[DateOfFirstBuy]
, 9, "September", 10, "October", 11, "November", 12, "December"
, 5, "May", 6, "June", 7, "July", 8, "August"
, "Unknown month number" )
"DateOfFirstBuy", MIN ( Sales[OrderDate] )
"CountOfNewCustomers", [NewCustomers]
[CountOfNewCustomers] > 0
)
ORDER BY 'Date'[FullDate]
, "Reseller Sales", SUMX(RELATEDTABLE(ResellerSales_USD),
ResellerSales_USD[SalesAmount_USD])
SUMMARIZE(SalesTerritory, SalesTerritory[SalesTerritoryGroup])
CROSSFILTER ( BridgeAccountsCustomers[AccountKey],
Accounts[AccountKey], Both )
Balance M2M optimized:=IF (
ISCROSSFILTERED ( Customers[CustomerKey] ),
CALCULATE ( [Balance Last Date], BridgeAccountsCustomers ),
[Balance Last Date]
)
By doing so, you’d get to create relationships between your tables—and you’d
have more cohesive results at that, too.
Show Active Orders
If you’re running a business or trying out DAX, you’d notice that a good way to
practice what you have learned is by checking which orders are actually
considered active or prolific in given tables.
You need to do this because it’ll help you trim down certain orders that are no
longer in effect, or that have not been followed through—extremely helpful for
stores to filter out which customers are good, and who among them are just joy
reservers. The challenge here is to be good with filtering out what you no
longer need, so suppose you’re working on the table below:
ND Column
function Labels
Row 2005 2006 2007 2008 Grand
Labels Total
Wheels
Vests
Touring
Frames
Touring
Bikes
Tires and Internet
Tubes Hit
Tights
Socks
Shorts
Saddles
Road
Frames
Road Bikes
Pumps
Pedals
Panniers
Mountain
Frames
Mountain
Bikes
Locks
Lights
Jerseys
Hydration
Packs
Helmets
Headsets
Handlebars
Gloves
Forks
Fenders Internet
Hit
Derailleurs
Cranksets
Cleaners
Chains
Caps
Brakes
Bottom
Brackets
Bottles and Internet
Cages Hit
Bike Internet
Stands Hit
Bike Racks
Bib-Shorts

Grand
Total
You can then use the following formula below to check out the active orders,
and get rid of those that aren’t:
FirstDate :=
IF (
ISCROSSFILTERED ( 'Date'[Date] ),
MIN ( 'Date'[Date] ),
TODAY ()
)

LastDate :=
IF (
ISCROSSFILTERED ( 'Date'[Date] ),
MAX ( 'Date'[Date] ),
TODAY ()
)
See, when it comes to organization, DAX could really help you out a lot—and
more!
Data Import
A lot of people get confused about Data Import, thinking they have no idea
what needs to be done. Say, you have the following table below:
Blue Crosshatch serif embossed
Blue Crosshatch sans-serif engraved
Green Vertical Stripe serif embossed
Green Vertical Stripe sans-serif engraved
Red Horizontal Stripe serif embossed
Red Horizontal Stripe sans-serif engraved

How do you think would you be able to import data from it to other tables, or
just to another part of the same table without damaging what you see? Well, for
that matter, DATAIMPORT becomes necessary, and you can do it this way:
DATAIMPORT( <result_columnName>, <search_columnName>,
<search_value>[, <search_columnName>, <search_value>]…)
What you can expect is that the value result_column would be returned when
you have a match for search_value, and search_column, amongst others. If you
cannot have all these values satisfied, you’d have to expect that a BLANK will
be returned, and a lookup will not be returned, especially if you have not met
the given criteria.
Then, if you are going to work on multiple rows, you can expect that search
values would be matched if identical values could be returned.
It covers the following parameters:
1. Search_value, or when the scalar expression does not refer to any specific
columns;
2. Search_columnname, or when you’re trying to search for the name of a
specific column, and could only be searched when using standard DAX
syntax. Otherwise, it would not work, and;
3. Result_columnname, or the name of a column that’s already existing, and
which you want to have a returned value from. You can name this using
standard DAX syntax, as well.
You also have to keep the following in mind:
1. Include only the columns that matter to you in your view.
2. Create a view for each of the tables that you have, so that in the same
schema, you could create the Power BI Data Model.
3. Make another schema for data models, so that they could take the name of
the same group of reports, or could share the same data for a certain model.
4. Make sure to use only data that are useful so as not to clog up your
program.
Filtering Columns
You know how filters can help you out a lot, right? When you filter columns,
you get to work on canonical schemas, and understand what needs to be
modified in your system. By following the instructions below, you could also
get to retrieve some of the columns that you may have lost early on—perfect
especially when you’re dealing with a huge set of numbers.
So, for example, you’re dealing with the table below:
ProductCategory[ProductCategoryName]
SalesTerritory[SalesTerritoryGroup]
Pacific Accessories
Pacific Bikes
Pacific Clothing
Pacific Components
North America Accessories
North America Bikes

North America Clothing

North America Components

Europe Accessories
Europe Bikes

Europe Clothing
Europe Components

You’d basically just have to follow the codes below to get what you need out
of the said table:
SpecialDaySales :=
VAR SpecialDates =
VAR AfterSpecialDates =
UNION (
UNION (
SELECTCOLUMNS (
SELECTCOLUMNS (
SELECTCOLUMNS (
SELECTCOLUMNS (
RETURN
FILTER ( 'Date', 'Date'[SpecialDay] = "Special Offer Day" ),
FILTER ( 'Date', 'Date'[SpecialDay] = "Special Offer Day" ),
FILTER ( 'Date', 'Date'[Day Of Week] = "Sunday" ),
FILTER ( 'Date', 'Date'[Day Of Week] = "Saturday" ),
CALCULATE ( [Sales Amount], SpecialDates )
AfterSpecialDaySales :=
"Date", [Date] + 1
"Date", [Date]
"Date", [Date]
"Date", [Date]

RETURN
CALCULATE ( [Sales Amount], AfterSpecialDates )
Filter Calculate Puzzles
If you may recall, the Calculate Function is able to help you calculate an
expression whose context is modified by filters that you have just specified. It
uses the following syntax:
CALCULATE(<expression>,<filter1>,<filter2>…)
The value that it returns is basically the result of the expression, and it covers
the following parameters:
1. Expression, or the expression that needs to be evaluated, and;
2. Filters, which should be separated by commas (filter 1, filter 2, etc.) to
serve as Boolean Expressions.
You have to take note, though, that you cannot use the given expression as a
measure, and that it could not be nested in a calculated manner, and cannot be
used in any function without the presence of a table.
Now, the problem here is that you’ve got to calculate override scenarios from
data taken from only two tables. This means that you have to create a
relationship between the two so that they’d work in the way you expect. What
are you supposed to do, then?
Well, first, look at the table below:

http://www.sqlbi.com/wp-content/uploads/Unexpected-filter-behavior-in-CALCULATE-01.png
What you can do here is code what you see below:

Sales[SumOfSales] :=
SUMX (
Sales[SalesOfMarch] :=
Sales[SalesOfMarch] :=
Sales[Quantity] * Sales[Net Price]
Sales,
FILTER ( ALL ( 'Date'[Month] ), 'Date'[Month] = "March" )
'Date'[Month] = "March”
CALCULATE (
CALCULATE (
[SumOfSales],
[SumOfSales],
)
Then, you’d get the results below:
http://www.sqlbi.com/wp-content/uploads/Unexpected-filter-behavior-in-CALCULATE-02.png
Use Relationship Puzzle
Finally, there’s the Use Relationship Puzzle. Since it’s the last puzzle, it’s
actually tricky—no codes would be given, but you have to keep in mind that
what you have to do here is activate one relationship, and then go ahead and
deactivate the other. Seems tricky, huh?
Go look at the image below:

http://www.sqlbi.com/wp-content/uploads/USERELATIONSHIP-Schema.png

Now, the challenge here is to compute difference in days between delivery


date, and the order of the date so that you could filter the query, and get the
result below:
http://www.sqlbi.com/wp-content/uploads/USERELATIONSHIP-Expected-Result.png\

Again, no formulas—you have to think about that yourself, but here are some
tips: create a column in sales that is calculated with the order date, then create
a calculated column, also under Sales, with the delivery date. Finally, compute
the third column by trying to get the average—and see what you’d end up with!
Good luck!
Chapter 14 Troubleshooting and Final Tips

Finally, you can keep in mind that troubleshooting formulas is easier than you
think because DAX flags wrong formulas right away. The only thing you’ve got
to remember now is that there are different kinds of errors, and they could
either be:
Semantic. This means that code execution is the problem, or is showing the
start of the problem. This doesn’t really have anything to do with the way
statements are constructed, but have a lot to do with what they mean—and
could show what’s wrong with variables, and non-variables, in general.
Syntax. Syntax errors mean that you’re using the wrong syntax for the various
functions that are involved in DAX. When you use grammatically incorrect
statements, chances are, code input would be wrong, as well. Typical reasons
for having syntax problems are misplaced reserved words, unbalanced
parentheses, misplaced semi-colons, and the like.
What causes these are:
1. The fact that formulas may refer to other columns, as opposed to the one
you are working on;
2. The formula deems a column that’s already erroneous, which means any
value from your formula would now be deemed invalid;
3. The formula gives you back incorrect parameters, or number types;
4. The formula seems to be correct, but the issue is that when the engine tries
to fetch it, a mismatch happens—and thus, results in an error.
5. The formula is about a column that has not been processed yet, and that’s
why the system could not comprehend what it is about.
By being mindful of the errors you might be making, you’d get to make sure that
your formulas would only be done right.
Tips to Keep in Mind
And, to make sure that DAX learning would be truly smooth-sailing for you, it
would be helpful to keep the tips below in mind:
1. You would learn from Power Pivot—and not an Excel Base. If you have
been reading this book right, you would notice that although they look the
same, DAX is actually different from Excel. You wouldn’t learn right if
you’d only open your Excel, and try to place these formulas there. It
wouldn’t hurt to open Power Pivot, and see how these things work for you.
Sure, it seems intimidating at first, but surely, with enough patience, you’d
get the hang of Power Pivot, too.
2. Don’t place too many Custom Columns on your tables—especially if
you have no idea which formulas are the right ones to use. Again, this
comes from being so used to Excel, so before you ruin your chance of
learning exactly how DAX works, it’s best to make sure that you’d stop
yourself from adding too many custom columns in your data table. Not only
are they not nice to look at, they’re hard to formulate, too—so you might
want to avoid that.
3. Build big DAX Formula in single steps. You’ve seen the kind of formulas
that are in this book, so what you can do is keep track of them by jotting
them down on a notebook. It also does not work like Access, so keeping
track of what you need to keep those programs running would be a big help!
4. Being passive. You cannot learn DAX in just one sitting! That would be
impossible. However, if you give it enough time and attention, you’d surely
be able to understand what it is about—and learn to give it your best shot,
too!
5. Not using proper naming conventions! And lastly, you have to keep in
mind that column reference is the table | column name, while measure
reference is the measure name. By keeping these two in check, those
formulas might even come naturally to you.
Keep these in mind, and surely, DAX wouldn’t be a problem for you!
Conclusion

Thank you for reading this book!


Hopefully, with the help of this, you’ve picked up a thing or two about DAX—
and that you’re willing to learn more about it now!
While it seems complicated at first, with commitment and patience—and by
following this book, you can be sure that you’d learn DAX—and it would be
easy for you!
Finally, if you enjoyed this book, kindly post a review. It will be greatly
appreciated.
Thank you, and good luck!

Você também pode gostar