Logical Operators:
NOT
is negation.IN
can search elements in a list.&&
and AND
both represent the logical AND.||
and OR
both represent the logical OR.
@icon-info-circle See pg. 112 for complete list of DAX operators.
@icon-info-circle
LEN
should be used on text values or with aFORMAT
nested inside of it.
FIND
and SEARCH
are useful for finding substrings.
@icon-warning
FIND
is case-sensitive, where asSEARCH
is not.
@icon-warningFIND
will propagate an error if no match is found. To avoid this, specifiy the 4th parameter in the function.
IFERROR
also exists in DAX and works the same way as in Excel.
@icon-info-circle DAX indexes from 1, while M indexes from 0.
SUBSTITUTE
also exists in DAX and works by replacing a specified substring with a replacement string.
@icon-warning
SUBSTITUTE
is case-sensitive.
RELATED
works in a 1:Many relationship the following way: (Data flow is 1 @icon-arrow-right Many).@icon-info-circle See pg. 117 for a list of DAX mathematical functions.
@icon-info-circle See pg. 118 for a list of DAX datetime functions.
LOOKUPVALUE
is invaluable for JOINING material based on multiple conditions. Think of it as a T-SQL JOIN with multiple ON statements.LOOKUPVALUE
’s syntax is as follows:
LOOKUPVALUE
returns an error if multiple matches exist for the given search conditions.
@icon-info-circle To see other techniques for looking up values in DAX, read this article by Marco Russo.
SWITCH
’s parameters are as follows:
@icon-info-circle
SWITCH
is great for replacing multiple nestedIF
statements. @icon-info-cirlce Use theSWITCH ( TRUE(), ... )
pattern for matching Boolean statements.
@icon-warning Calculated columns cannot be sorted by subsequent, dependent calculated columns.
@icon-warning Variables can only be accessed within the DAX EXPRESSION that they are defined in.
@icon-warning Calculated columns consume RAM.
@icon-info-circle Filter context cannot distinguish between identical rows in an iterative structure.
@icon-info-circle Source columns used for sorting are also propagated throughout filter context.
SUM
, AVERAGE
, COUNTROWS
, etc.
@icon-warning By default, row context ignores any established relationships unless
RELATED
orRELATEDTABLE
are explicitly used.
CALCULATE
transforms row context into filter context (CALCULATE
: row context @icon-arrow-right filter context).
SUMX
@icon-arrow-right 1. Filter table rows. 2. Perform primative SUM
aggregation).
@icon-info-circle
RELATEDTABLE
is an alias forCALCULATETABLE
.
@icon-info-circle To learn more context transition, read Understanding Context Transition by Alberto Ferrari. Visit the various articles on www.sqlbi.com to better understand all aspects of DAX evaulation context.
CALCULATE
with identical DAX expressions create an implicit Circular Dependency Error
. This is a byproduct of the context transition.For example:
#table ( type table [ Scale = Int64.Type ], {} )
@icon-info-circle When DAX detects a primary key column, context transition works differently: DAX knows it can rely on the column have unique row values, so it uses that column to filter the remaining columns in the table without using values from the other columns.
In other words, the context transition is column @icon-arrow-right columns instead of row @icon-arrow-right columns.
@icon-info-circle For more details on circular dependencies in DAX, see the following two articles:
- https://www.sqlbi.com/articles/understanding-circular-dependencies
- https://www.sqlbi.com/articles/avoiding-circular-dependency-errors-in-dax
CALCULATETABLE
only has one required parameter.Sales Duplicate Table = 'Sales'
).FILTER
function is evaluated in row context for each row of the table from the table parameter.FILTER
does not trigger context transition. It is essentially a TSQL WHERE
statement.
@icon-warning When
FILTER
is used in context transition, it generates new row context. This means that for each row in the base table (where the calculated column is being created), the iteration is performed against the rows of the table inFILTER
and not the rows in the base table.
EARLIER
function. This action is simialr to an excel SUMIF
.FILTER
.@icon-info-circle To aid in DAX expressions where a table references its
EARLIER
rows, use a variable before theCALCULATE
. @icon-info-circle It is important to remember that when you perform context transition in large tables, the operation is much slower that filtering column values. Therefore, instead of filtering a table and doing context transition, it is advisable to pre-calculate the results in a calculated column and then filter by the column.
ALL
can be used to create calculated tables.ALL
returns a table of every disticnt combination of the columns.ALL
cannot accept another function as an argument.ALL
cannot accept multiple columns from different tables as its parameter.
@icon-info-circle Recall that a calculation function such as
SUM
that is not wrapped in aCALCULATE
is often equivalent to wrapping the same function in aCALCULATE
and nestingALL
inside the filter parameter.
@icon-warning Recall that, for a table on the Many side of a 1:Many relationship, if it contains rows not found in the table on the 1 side, DAX creates a virtual
BLANK
row in the 1 table that is invisible by default.
@icon-warningALL
includes virtual rows.
FILTER
.ALLNOBLANKROW
function.
@icon-info-circle Recall that
ALLNOBLANKROW
does not filter out true blank rows. Otherwise, it works the same asALL
.
ALLEXCEPT
ALLEXCEPT
receives a table as the first parameter and a list of excluded columns in the following parameter.ALLEXCEPT
is also useful for calculating subtotals in calculated columns without the need of EARLIER
or var
.RELATEDTABLE
is an alias for CALCULATETABLE
only when one argument is used.FILTER
, CALCULATETABLE
can accept more than one filter parameter.
OR
, they must be on the same column.
@icon-info-circle Recall that
CALCULATE
andCALCULATETABLE
internally transform Boolean filter parameters into equivalentCALCULATE(...,ALL()...)
tables.
@icon-info-circle For more information on the filter arguments in
CALCULATE
, see “Fitler Arguments inCALCULATE
” at https://www.sqlbi.com/articles/filter-arguments-in-calculate/.
@icon-warning
VALUES
can only receive a physical table.DISTINCT
can also receive a table expression.
@icon-warning
VALUES
includes virtual blank rows.DISTINCT
does not include virtual blank rows.
SUMMARIZE
’s two parameters:
@icon-info-circle If referencing the Many table in a 1:Many relationship where the Many table contains values missing from the 1 table, then
SUMMARIZE
andSUMMARIZECOLUMNS
will include the virtual blank row.
However, if summarizing the 1 table, the virtual blank row will not be included.
@icon-info-circle However,SUMMARIZECOLUMNS
will include the virtual blank row, regardless of which table.
SUMMARIZE
does not grant access to the row context of the table being summarized. Instead, SUMMARIZE
divides the table into parts, grouping them by the selected columns, where each part of the original table retains its filter context. SUMMARIZE
.SUMMARIZECOLUMNS
, unlike SUMMARIZE
, does not require a table parameter. Instead, the columns themselves are simply listed.
@icon-info-cirlce Read “All the secrets of
SUMMARIZE
” by Marco Russo and Alberto Ferrari at https://www.sqlbi.com/articles/introducing-summarizecolumns.
ADDCOLUMNS
creates row context in the proecss of it adding new columns.ADDCOLUMNS
takes three required parameters:
ADDCOLUMNS
Functionality:
@icon-warning Unlike in
SUMMARIZE
,ADDCOLUMNS
requires context transition that must be initialized through a nestedCALCULATE
.
CALCULATE
, you can reference columns in the table to which you are adding more columns to.SELECTCOLUMNS
is very similar to ADDCOLUMNS
, except that the original columns are not kept.
@icon-warning
SELECTCOLUMNS
does not remove duplicate rows.
SELECTCOLUMNS
can be grouped by extension columns referencing the column(s) inside of SELECTCOLUMNS
within SUMMARIZE
.SELECTCOLUMNS
can be nested inside of a SUMMARIZE
, and the second parameter of SUMMARIZE
can reference the column(s) from SELECTCOLUMNS
.
@icon-info-circle Recall that when parameter two of
SUMMARIZE
references parameter one ofSUMMARIZE
, the column(s) being referenced in parameter two must be referenced without a table name. @icon-info-circleSELECTCOLUMNS
can be used to rename columns. See https://blog.crossjoin.co.uk/2015/06/01/using-selectcolumns-to-alias-columns-in-dax/.
TOPN
has three required parameters and one optional parameter:
@icon-info-circle
TOPN
uses row context, soCALCLATE
is required inside ofTOPN
to force context transition.
@icon-warning In the case of a tie, more rows are returned than expected.
@icon-info-circle WithTOPN
, it is also possible to order by more than one expression: in this case, expressions and orders come in pairs after the first expression and order pair.
CROSSJOIN
creates a Cartesian product between two or more tables.
SELECTCOLUMNS
, see pg. 153).
@icon-warning There is no row context or context transition in
CROSSJOIN
for the second or subsequent tables. Consequently, to reference the current row of the first table inCROSSJOIN
, useGENERATE
. However,CALCULATE
can be used as a nested function for the second (or subsequent) table expression parameters.
GENERATE
always receives two table expressions as parameters.GENERATEALL
works the same way as GENERATE
except that it returns all possible combinations.GENERATESERIES
generates a table with one column, called Value, containing a list of numbers with predefined increment.
@icon-info-circle These values need not exist in the DAX Data Model.
GENERATESERIES
parameters:
@icon-warning If Start value > End value, the result is a zero-row table.
GENERATESERIES
automatically detects the data type being generated. Data types can also be explicitly specified in GENERATESERIES
.GENERATESERIES
can be used to generate a list of datetime values.
@icon-info-circle To use hourly increments, utilize the
TIME
function.
GENERATESERIES
can also generate a list of letters by combining SELECTCOLUMNS
and UNICHAR
.UNICHAR
takes a positive integer as its only parameter and returns a Unicode character.CALENDER
generates a table of datetime data type.CALENDERAUTO
searches all date and datetime columns in the entire DAX Data Model and finds the minimum date and maximum date. It then takes 1 January of the minimum date’s year through 31 Decemeber of the maximum date’s year.
CALENDARAUTO
has one optional third parameter, which is the fiscal year end month number.
@icon-info-circle
MIN
andMAX
allow for the comparison of two scalar values.
ROW
allows for the creation of one-row tables containing multiple columns.
ROW
’s parameters come in pairs:
@icon-info-circle
ROW
can be useful when adding a new row to a table usingUNION
.
UNION
combines tables vertically.UNION
.UNION
’s output table will have the same column names as the first table parameter.UNION
can be used to create common dimensions from several different tables.@icon-warning If aligned columns in a
UNION
have differing data types, they will be combined in accordance with DAX data type coercion (e.g. type Text overrules type Whole Number).
@icon-info-circle Power Query’s
APPEND
combines tables vertically. It is essentially aUNION
.
@icon-info-circle Recall that tables can be hidden in the DAX Data Model.
INTERSECT
combines tables based on the position of those columns.@icon-warning
INTERSECT
will retain duplicate matches from the first table parameter. This is why, technically, order matters inINTERSECT
.
EXCEPT
takes two tables as arguments and outputs all rows that exist in the first table parameter but not the second table parameter.@icon-warning
EXCEPT
will retain duplicate matches from the first table parameter. This is why, technically, order matters inEXCEPT
.
NATURALINNERJOIN
is quite similar to Power Query’s Merge
function: it receives two tables as arguments and joins them based on common column names.NATURALINNERJOIN
joins two tables and outputs a table that has the same values present in join columns of both tables.
@icon-info-circle If the JOIN columns have different names in each table, then
NATURALINNERJOIN
will add each name as a separate column in the result table.
NATURALINNERJOIN
when considering the order of the JOIN columns.NATURALINNERJOIN
can also join physical tables that have a relationship between them.
JOIN
.NATURALINNERJOIN
. Otherwise, the function will produce an error.
@icon-info-circle In general, all column names in materialized DAX tables should be unique. However, virtual tables are allowed to share column names in some cases.
CALCULATE
and CALCULATETABLE
.NATURALLEFTOUTERJOIN
returns:
NATURALLEFTOUTERJOIN
can also join physical tables that have a relationship between them.DATATABLE
allows you to create calculated tables with data that you enter manually.DATATABLE
as a minimum of three parameters:
@icon-info-circle Think of a value in the third parameter of
DATATABLE
as an entire row. Thus, the row itself is wrapped in {}, not each column value of a row (e.g. {1, “String”, TRUE}).
@icon-warning The values in the third parameter must be constants. DAX expressions are not allowed.
- An actual table can be created within
DATATABLE
by listing column names and data types in pairs before the third parameter (the list of values). @icon-info-circle Think ofDATATABLE
similar toSUMMARIZE
over a manually created table.
@icon-info-circle To read more about
DATATABLE
, see Marco Russo’s article Create Static Tables in DAX Using the DATATABLE Function.
@icon-warning Remember that variables are only evaluated once in the context in which they are defined. Because of this, they are USELESS in iterator functions like
CALCULATE
andCALCULATETABLE
. In other words, variables are immutable after the first evaulation.
@icon-info-circle To see more information about using
GENERATE
/ROW
instead ofADDCOLUMNS
, see Using GENERATE and ROW instead of ADDCOLUMNS in DAX.
@icon-info-circle Measures aggregate columns and tables, and they always work in filter context. Consequently, by default, there is no concept of the current row in measures. You cannot create a measure in the same way that you can a calculated column, iterating row by row through a table.
SUM
, AVERAGE
, MIN
, MAX
, etc. take a column reference as their once parameter. They are essentially syntatic sugar for their iterator foundations.Total Net Profit = SUM ( Example[Net Profit] )
Total Net Profit = SUMX ( Example, Example[Net Profit] )
RELATED
) can be used in them.@icon-warning Recall that measures cannot be placed into slicers.
COUNT
COUNTA
COUNTAX
COUNTBLANK
COUNTROWS
COUNTX
DISTINCTCOUNT
@icon-info-circle Recall that:
COUNTROWS
takes a table expression as its parameter.COUNT
takes a column reference as its parameter and counts the number of non-blank values.COUNT
cannot handle Boolean values.COUNTA
counts the number of non-blank values regardless of their datatype.