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
LENshould be used on text values or with aFORMATnested inside of it.
FIND and SEARCH are useful for finding substrings.
@icon-warning
FINDis case-sensitive, where asSEARCHis not.
@icon-warningFINDwill 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
SUBSTITUTEis 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
SWITCHis great for replacing multiple nestedIFstatements. @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
RELATEDorRELATEDTABLEare 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
RELATEDTABLEis 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
FILTERis 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 inFILTERand 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
EARLIERrows, 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
SUMthat is not wrapped in aCALCULATEis often equivalent to wrapping the same function in aCALCULATEand nestingALLinside 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
BLANKrow in the 1 table that is invisible by default.
@icon-warningALLincludes virtual rows.
FILTER.ALLNOBLANKROW function.
@icon-info-circle Recall that
ALLNOBLANKROWdoes 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
CALCULATEandCALCULATETABLEinternally 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
VALUEScan only receive a physical table.DISTINCTcan also receive a table expression.
@icon-warning
VALUESincludes virtual blank rows.DISTINCTdoes 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
SUMMARIZEandSUMMARIZECOLUMNSwill include the virtual blank row.
However, if summarizing the 1 table, the virtual blank row will not be included.
@icon-info-circle However,SUMMARIZECOLUMNSwill 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,ADDCOLUMNSrequires 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
SELECTCOLUMNSdoes 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
SUMMARIZEreferences parameter one ofSUMMARIZE, the column(s) being referenced in parameter two must be referenced without a table name. @icon-info-circleSELECTCOLUMNScan 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
TOPNuses row context, soCALCLATEis required inside ofTOPNto 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
CROSSJOINfor the second or subsequent tables. Consequently, to reference the current row of the first table inCROSSJOIN, useGENERATE. However,CALCULATEcan 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
TIMEfunction.
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
MINandMAXallow 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
ROWcan 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
UNIONhave 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
APPENDcombines 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
INTERSECTwill 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
EXCEPTwill 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
NATURALINNERJOINwill 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
DATATABLEas 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
DATATABLEby listing column names and data types in pairs before the third parameter (the list of values). @icon-info-circle Think ofDATATABLEsimilar toSUMMARIZEover 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
CALCULATEandCALCULATETABLE. In other words, variables are immutable after the first evaulation.
@icon-info-circle To see more information about using
GENERATE/ROWinstead 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.
COUNTCOUNTACOUNTAXCOUNTBLANKCOUNTROWSCOUNTXDISTINCTCOUNT
@icon-info-circle Recall that:
COUNTROWStakes a table expression as its parameter.COUNTtakes a column reference as its parameter and counts the number of non-blank values.COUNTcannot handle Boolean values.COUNTAcounts the number of non-blank values regardless of their datatype.