DAX Functions
DAX Functions
Data Analysis
Expressions
DAX works only on tables. All the formulas must reference columns inside
tables.
Sales[SalesAmount] = Sales[ProductPrice] * Sales[ProductQuantity]
DAX works on a data model containing many tables.
AllSales = SUM ( Sales[SalesAmount] ) //column level --- it is the grand total of the
SalesAmount column.
AllSales :=SUMX ( Sales, Sales[ProductQuantity] * Sales[ProductPrice])
Calculated Columns:
Calculated columns are used when you want to perform row by row.
Ex: margin of sales, profit of the sales
Calculated columns are added to table as a column.
Calculated column values are stored in the powerbi.pbix file. Each calculated
column will increase the space that is used in that file and potentially increase
the refresh time.
Calculated columns are very bad at aggregations because they don’t know about
how to filter.
When we refresh new column values are re-calculated
Name must be unique in table level.
Measures:
Measures are calculated on demand. Power bi calculate the correct value when
the user requests it.
EX. When we drag the total sales measure onto the report, power bi calculate the
correct total and display it on visual.
Measures do not add to the overall disk space of the power bi .pbix file.
Measures are calculated based on the filters that are used by the report user.
These filters combine to create the filter context.
Name must be unique across all tables.
For measures we can add currency sign (measure tools->choose one in list of
currency types).
Measures are two types
1. Implicit measure (Basic aggregation, No formula, direct drag column from table)
2. Explicit measure (complex aggregation, with formula, drag measure from the table)
Operators:
All comparison operators except == treat BLANK as equal to number 0, empty string "",
DATE(1899, 12, 30), or FALSE. As a result, [Column] = 0 will be true when the value of
[Column] is either 0 or BLANK. In contrast, [Column] == 0 is true only when the value of
[Column] is 0.
Text concatenation operator -
& (ampersand) => Concatenation
Example => [First Name] & ',' & [Last Name]
Logical operators –
Use logical operators (&&) and (||) to combine expressions to produce a single
result.
The AND function in DAX accepts only two (2) arguments. If you need to perform an
AND operation on multiple expressions, you can create a series of calculations or, better,
use the AND operator (&&) to join all of them in a simple expression.
The logical operator || returns TRUE if any of the arguments are TRUE and returns
FALSE if all arguments are FALSE. With two arguments it works as the OR function. However,
the operator makes it easier to include multiple conditions in the same expression, because
the OR function only has two arguments and requires multiple calls for three or more
arguments.
SWITCH (
'Product'[Category],
"Audio", 0.15,
"Computers", 0.2,
"Cell phones", 0.13,
0
)
Writing TRUE() or TRUE produces the same result.
Stock Category = SWITCH(
True(),
Calendar[Month]="Jan", "January",
Calendar[Month] ="Feb", "February",
Calendar[Month] ="Mar", "March",
Calendar[Month] ="Apr", "April",
Calendar[Month] ="Jun", "June",
Calendar[Month] ="Jul", "July",
Calendar[Month] ="Aug", "August",
Calendar[Month] ="Sep", "September",
Calendar[Month] ="Oct", "October",
Calendar[Month] ="Nov", "November",
Calendar[Month] ="Dec", "December",
ISBLANK(Calendar[Month]),"null"
)
Stock Category = SWITCH(
Calendar[Month],
1, "January",
2, "February",
3, "March",
4, "April",
5, "May",
6, "June",
7, "July",
8, "August",
9, "September",
10, "October",
11, "November",
12, "December",
"null"
)
Variables in DAX
You can define a variable in any DAX expression by using VAR followed by RETURN. In one or several
VAR sections, you individually declare the variables needed to compute the expression; in the
RETURN part you provide the expression itself.
Discounted Sales =
VAR AverageSales = AVERAGEX( Customer, [Sales Amount] )
VAR Result =
SUMX (
Customer,
VAR CustomerSales = [Sales Amount]
VAR Discount = 0.85
VAR Result =
IF (
CustomerSales >= AverageSales,
CustomerSales * Discount,
CustomerSales
)
RETURN
Result
)
RETURN
Result
Discounted Sales =
VAR AverageSales = AVERAGEX( Customer, [Sales Amount] )
VAR CustomerSales = [Sales Amount]
VAR Discount = 0.85
VAR Result =
SUMX (
Customer,
IF (
CustomerSales >= AverageSales,
CustomerSales * Discount,
CustomerSales
)
)
RETURN
Result
Discounted Sales =
SUMX (
Customer,
VAR AverageSales = AVERAGEX ( Customer, [Sales Amount] )
VAR CustomerSales = [Sales Amount]
VAR Discount = 0.85
VAR Result =
IF (
CustomerSales >= AverageSales,
CustomerSales * Discount,
CustomerSales
)
RETURN
Result
Aggregate DAX Function:
1. Sum(),Sumx():
SUM(<column>) //The column that contains the numbers to sum.
SUMX(<table>, <expression>)
Only the numbers in the column are counted. Blanks, logical values, and text are ignored.
2. MAX(), MIN()
MAX(<expression1>, <expression2>)
MAX(<column>)
MIN(<column>)
MIN(<expression1>, <expression2>)
These functions support below datatypes. But these are not supporting boolean data
types
Numbers
Texts
Dates
Blanks // blank values are ignored
Only When comparing two expressions, blank is treated as 0 when comparing. That is,
Max(1, Blank() ) returns 1, and Max( -1, Blank() ) returns 0.
If both arguments are blank, MAX returns a blank. If either expression returns a value
which is not allowed, MAX returns an error.
TRUE/FALSE values are not supported. If you want to evaluate a column of TRUE/FALSE
values, use the MAXA function.
max_m = MAX(blank column) -> returns blank value
3. MAXA(),MINA():
MAXA(<column>)
MINA(<column>)
The MAXA function takes as argument a column, and looks for the largest value among
the following types of values:
Numbers
Dates
Blanks // blank values are ignored
Logical values, such as TRUE and FALSE. Rows that evaluate to TRUE count as 1; rows
that evaluate to FALSE count as 0 (zero).
If you want to compare text values, use the MAX function.
Maxa(string column) -> returns 0 value.
4. MAXX() , MINX()
MAXX(<table>,<expression>,[<variant>])
MINX(<table>, < expression>,[<variant>])
These functions support below datatypes:
Numbers
Texts
Dates
Blank values are skipped.
TRUE/FALSE values are not supported.
If the expression has variant or mixed value types such as text and number, then by
default MAXX considers only numbers. If <variant> = TRUE``, the maximum value is
returned.
max_m = maxX(orders,Orders[Category]*Orders[Sales]) //ERROR
max_m = maxX(orders,Orders[Category]*Orders[Sales],TRUE) //ERROR
max_m = maxX(orders,Orders[Category]*Orders[Sales],FALSE) //ERROR
max_m = maxX(orders,Orders[Category]) //OK
max_m = maxX(orders,blank column) //OK returns blank value
5. AVERAGE ,
AVERAGE(<column>)
This function takes the specified column as an argument and finds the average of the
values in that column. If you want to find the average of an expression that evaluates to
a set of numbers, use the AVERAGEX function instead.
Nonnumeric values in the column are handled as follows:
If the column contains text, no aggregation can be performed, and the functions
returns blanks.
If the column contains logical values or empty cells, those values are ignored.
Cells with the value zero are included.
When you average cells, you must keep in mind the difference between an empty cell
and a cell that contains the value 0 (zero). When a cell contains 0, it is added to the sum
of numbers and the row is counted among the number of rows used as the divisor.
However, when a cell contains a blank, the row is not counted.
Whenever there are no rows to aggregate, the function returns a blank. However, if
there are rows, but none of them meet the specified criteria, the function returns 0.
Excel also returns a zero if no rows are found that meet the conditions.
max_m = AVERAGE(Orders[Sub-Category]) //ERROR
max_m = AVERAGE(Blank Column) //BLANK
6. AVERAGEA
AVERAGEA(<column>)
The AVERAGEA function takes a column and averages the numbers in it, but also handles
non-numeric data types according to the following rules:
Values that evaluate to TRUE count as 1.
Values that evaluate to FALSE count as 0 (zero).
Values that contain non-numeric text count as 0 (zero).
Empty text ("") counts as 0 (zero).
If you do not want to include logical values and text representations of numbers in a
reference as part of the calculation, use the AVERAGE function.
max_m = AVERAGEA(Orders[Sub-Category])//OK
max_m = AVERAGEX(Blank Column) //BLANK
Whenever there are no rows to aggregate, the function returns a blank. However, if
there are rows, but none of them meet the specified criteria, the function returns 0.
Microsoft Excel also returns a zero if no rows are found that meet the conditions.
7. AVERAGEX
AVERAGEX(<table>,<expression>)
The AVERAGEX function enables you to evaluate expressions for each row of a table, and
then take the resulting set of values and calculate its arithmetic mean. Therefore, the
function takes a table as its first argument, and an expression as the second argument.
In all other respects, AVERAGEX follows the same rules as AVERAGE. You cannot include
non-numeric or null cells. Both the table and expression arguments are required.
When there are no rows to aggregate, the function returns a blank. When there are
rows, but none of them meet the specified criteria, then the function returns 0.
8. COUNT , COUNTROWS
COUNT(<column>) Counts the number of rows in the specified column that contain non-
blank values.
COUNTROWS([<table>])The COUNTROWS function counts the number of rows in the
specified table, or in a table defined by an expression.
9
Item_Table
Sheet1
11
9. COUNTA
Counts the number of rows in the specified column that contain non-blank values.
Unlike COUNT, COUNTA supports Boolean data type.
10. COUNTX,COUNTAX
Counts the number of rows that contain a non-blank value or an expression that evaluates
to a non-blank value, when evaluating an expression over a table.
11. COUNTBLANK
Counts the number of blank cells in a column.
COUNTBLANK(<column>)
12. DISTINCTCOUNT, DISTINCTCOUNTNOBLANK
Counts the number of distinct values in a column.
DISTINCTCOUNT(<column>)
DISTINCTCOUNT function counts the BLANK value. To skip the BLANK value, use the
DISTINCTCOUNTNOBLANK function.
13. PRODUCT, PRODUCTX
Returns the product of the numbers in a column.
PRODUCT(<column>)
Only the numbers in the column are counted. Blanks, logical values, and text are ignored.
RELATED/RELATEDTABLE:
VLOOKUP IN Excel=RELATED function in DAX
RELATED FUNCTION RULES:
1. Only works when there is an active one to many relationships between 2 tables.
2. You can write the related function only in many sides of the table.
3. This function works on row context like column calculation and iterator functions.
TOY
Toy Id
1
*
3. Concatenate ()
It concatenates two column values only
Concatenate (col1, col2)
Ex: concatenate (“gopi”, “Krishna”); o/p: gopiKrishna
CONCATENATE(Customer[LastName], CONCATENATE(", ", Customer[FirstName]))
4. concatenateX ()
it is used in measure.
Using CONCATENATEX to combine multiple rows by specified column value.
Suppose you want below report data
Department Heads
HR Gopi Department Heads_measure
IT Krishna HR Gopi, Vijay
CADEM Mallik IT Krishna, Goutham
HR Vijay CADEM Mallik
PED Ramesh PED Ramesh
IT Goutham
Using concatenateX function, we get the Heads list of values based on department.
Create a measure
Heads_measure= CONCATENATEX(<table>, <expression/column name > [, <delimiter> [,
<orderBy_expression/column name> [, <order>]] ...])
ASC: To sort in an ascending order.
DESC: To sort in a descending order.
If omitted, default is ASC.
Return value
A string containing value formatted as defined by format_string.
Note
If value is BLANK, the function returns an empty string.
If format_string is BLANK, the value is formatted with a "General Number" or
"General Date" format (according to value data type).
All comparison operators except == treat BLANK as equal to number 0, empty string "", DATE
(1899, 12, 30), or FALSE. As a result, [Column] = 0 will be true when the value of [Column] is either 0
or BLANK. In contrast, [Column] == 0 is true only when the value of [Column] is 0.
Logical operators:
&& or AND ()
|| or OR ()
IN { }
9. EOMONTH
The following expression returns May 31, 2008, because the months argument is rounded to
2.
= EOMONTH("March 3, 2008",1.5)
= EOMONTH("March 3, 2008",1.4) //30-04-2008 months argument is rounded to 1.
10. ENDOFMONTH (date column) – Time intelligence functions
Returns the last date of the month in the current context for the specified column of dates.
(it is not returning last date of month; it returns maximum date of every month)
ENDOFMONTH(<date column>|<table having single date column>)
This function returns maximum date available in the specified month and year in the
column.
11. ENDOFQUARTER
Returns the last date of the quarter in the current context for the specified column of dates.
ENDOFQUARTER(<dates>)
12. ENDOFYEAR
Returns the last date of the year in the current context for the specified column of dates.
ENDOFYEAR(<dates> [,<year_end_date>])
ENDOFYEAR(Orders[Order Date]) -> returns end date of each year in specified column of
dates.
ENDOFYEAR(Orders[Order Date],”31/03”)
01 Apr 2014 to 31 March 2015 shows 31 March 2015
ENDOFYEAR(Orders[Order Date],”31/03/2006”) (any year value you can take)
01 Apr 2014 to 31 March 2015 shows 31 March 2015
ENDOFYEAR(Orders[Order Date],”27/08”)
28 Aug 2014 to 27 Aug 2015 shows 27 Aug 2015
13. STARTOFMONTH
Returns the first date of the month in the current context for the specified column of dates.
STARTOFMONTH(<dates>)
14. STARTOFQUARTER
Returns the first date of the quarter in the current context for the specified column of dates.
STARTOFQUARTER(<dates>)
15. STARTOFYEAR
Returns the first date of the year in the current context for the specified column of dates.
STARTOFYEAR(<dates>)
16. HOUR (time column)
Returns the hour as a number from 0 (12:00 A.M.) to 23 (11:00 P.M.).
The following example returns 15, meaning the hour corresponding to 3 PM in a 24-hour
clock. The text value is automatically parsed and converted to a date/time value.
= HOUR("March 3, 2008 3:00 PM")
17. Minute (time column)
Returns the minute as a number from 0 to 59, given a date and time value.
MINUTE(<datetime>)
The following example returns 45, which is the number of minutes in the time 1:45 PM.
= MINUTE("March 23, 2008 1:45 PM")
18. Second (time column)
Returns the seconds of a time value, as a number from 0 to 59.
SECOND(<time>)
The following formula returns 3, which is the number of seconds in the time represented by
the value, March 3, 2008 12:00:03.
= SECOND("March 3, 2008 12:00:03")
19. Month (date column)
Returns the month as a number from 1 (January) to 12 (December).
MONTH(<datetime>)
The following expression returns 3, which is the integer corresponding to March, the month
in the date argument.
= MONTH("March 3, 2008 3:45 PM")
20. Year (date column)
Returns the year of a date as a four-digit integer in the range 1900-9999.
YEAR(<date>)
The following example returns 2007.
= YEAR("March 2007")
= YEAR(TODAY())
21. Quarter (date column)
Returns the quarter as a number from 1 (January – March) to 4 (October – December).
QUARTER(<date>)
22. Weekday (date column, return type)
Returns a number from 0 to 7 identifying the day of the week of a date.
Return type =1 then week begins Sunday (1) to Saturday (7)
Return type=2 then week begins Monday (1) to Sunday (7)
Return type=3 then week begins Monday (0) to Sunday (6)
23. WEEKNUM(date column ,return type)
Returns the week number in the year.
WEEKNUM(<date>[, <return type>])
return type Week begins on System
1 or omitted Sunday 1
2 Monday 1
11 Monday 1
12 Tuesday 1
13 Wednesday 1
14 Thursday 1
15 Friday 1
16 Saturday 1
17 Sunday 1
21 Monday 2
Column 4 = WEEKNUM('Date Table'[Date Value],2)
24. Networkdays
Returns the number of whole workdays between two dates (inclusive)
NETWORKDAYS(<start_date>, <end_date> [, <weekend>, <holidays>])
This function returns no of days between two dates. And also exclude the weekends,
holidays also.
<weekend> parameter:
1 or omitted: Saturday, Sunday
2: Sunday, Monday
3: Monday, Tuesday
4: Tuesday, Wednesday
5: Wednesday, Thursday
6: Thursday, Friday
7: Friday, Saturday
11: Sunday only
12: Monday only
13: Tuesday only
14: Wednesday only
15: Thursday only
16: Friday only
17: Saturday only
<holidays> table: A column table of one or more dates that are to be excluded from the
working day calendar.
NETWORKDAYS (DATE (2022, 5, 28), DATE (2022, 6, 05), 1,
{
DATE (2022, 5, 30), DATE (2022,6,01)
}
)
NETWORKDAYS (start date, end date,1, holidays table column)
25. NOW () –Returns the current date and time in datetime format.
Current datetime= now ();
The following example returns the current date and time plus 3.5 days:
= NOW()+3.5 13-03-2025 15:55:38 +3.5
=17-03-2025 03:56:11
26. TODAY () - Returns the current date.
=TODAY() 13-03-2025 00:00:00
27. UTCNOW () – returns the current date and time (UTC time value) in datetime format.
NOW() -> 13-03-2025 16:03:08 UTC+5:30
UTCNOW() -> 13-03-2025 10:33:08
28. UTCTODAY()
TODAY() -> March, 13 2025 [00:03:56 (Thursday) at UTC +05:30].
UTCTODAY() -> March, 12 2025 [18:33:56 (Wednesday) at UTC 0].
29. TIME (hour, minute, second) – return time value along with default date.
Time (06,20,30); o/p: 30-12-1899 06:20:30 here 30-12-1899 is default date
TIME(hour, minute, second)
Return value
A time (datetime) ranging from 00:00:00 (12:00:00 AM) to 23:59:59 (11:59:59 PM).
30. TIMEVALUE ()
Converts a time in text format to a time in datetime format.
= TIMEVALUE(time text)
= TIMEVALUE("20:45:30")
31. YEARFRAC
Returns the year fraction representing the number of whole days between start_date and
end_date.
YEARFRAC(<start_date>, <end_date>, <basis>)
YEARFRAC(“Jan 1 2007”,”Mar 2 2007”) -> 0.16944444444444
Calculation:
In Jan 2007 days: 31
In Feb 2007 days: 28
In Mar 2007 days: 2
Total days: 61
Now result= 61/360 =0.16944444444444444
YEARFRAC(“Jan 1 2007”,”Mar 2 2007”,1) -> 0.164383561643836
YEARFRAC(“Jan 1 2007”,”Mar 2 2007”,2) -> 0.16666666666667
YEARFRAC(“Jan 1 2007”,”Mar 2 2007”,3) ->
YEARFRAC(“Jan 1 2007”,”Mar 2 2007”,1) ->
Math Functions:
1. INT ()
Rounds a number down to the nearest integer. Remove Decimals
salaryInt=INT([salary]);
= INT(1.5) //rounds the value to 1
2. ABS
Returns the absolute value of a number.
ABS(<number>) //A decimal number.
3. Currency ()
Converts into money with decimals.
Evaluates the argument and returns the result as currency data type.
Salesamt=Currency ([salesAmount])
The CURRENCY function rounds up the 5th significant decimal, in value, to return the 4th
decimal digit. Rounding up occurs if the 5th significant decimal is equal or larger than 5. For
example, if value is 3.6666666666666 then converting to currency returns $3.6667. However, if
value is 3.0123456789 then converting to currency returns $3.0123.
CURRENCY(Orders[sales]) //$75.25
CURRENCY(TrueFalse) will return $1.0000 for True values and $0.0000 for False values.
4. Round ()
Rounds a number to the specified number of digits.
ROUND(<number>, <num_digits>)
If num_digits are greater than 0 (zero), then number is rounded to the specified number
of decimal places.
If num_digits are 0, the number is rounded to the nearest integer.
If num_digits are less than 0, the number is rounded to the left of the decimal point.
ROUND (2.15,1) o/p: 2.2
ROUND (21.5, -1) o/p: 20
ROUND(Orders[Sales],0) //ROUND THE VALUE
ROUND(Orders[Sales],-1)
Value value
Sales with -1 with -2
77.88 80 100
6.63 10 0
5.46 10 0
73.2 70 100
12.39 10 0
2.88 0 0
4.16 0 0
5. RoundUp ()
Its same like Round method
9. ISEVEN ()
Returns TRUE if number is even, or FALSE if number is odd.
ISEVEN (number)
10. ODD ()
Returns number rounded up to the nearest odd integer.
ODD (number)
= ODD (1.5) Rounds 1.5 up to the nearest odd integer. 3
= ODD (3) Rounds 3 up to the nearest odd integer. 3
= ODD (2) Rounds 2 up to the nearest odd integer. 3
= ODD (-1) Rounds -1 up to the nearest odd integer. -1
= ODD (-2) Rounds -2 up (away from 0) to the nearest odd integer. -3
11. ISODD ()
Returns TRUE if number is odd, or FALSE if number is even.
ISODD (number)
12. POWER ()
Returns the result of a number raised to a power.
POWER(<number>, <power>)
= POWER (5,2); 25
13. Sqrt ()
Returns the square root of a number.
SQRT(<number>)
= SQRT (25); 5
If the number is negative, the SQRT function returns an error.
14. Fact ()
Returns the factorial of a number, equal to 1*2*3*…* Number.
Fact (1) 1
Fact (5) 120
Fact (9) 362,880
15. Sign ()
Return 1, when the number is positive
Return 0, when the number is 0
Return -1, when the number is negative.
ProfitSign= sign ([profit]);
Scalar Functions
Scalar function in a function that returns one single value. This value can be of any data type;
Date, Numeric, Text, etc. But it is always one single value.
Sales = Sum (FactInternetSales [SalesAmount])
We have many Scalar functions in DAX, here are a few examples:
SUM/Average/Min/Max
SUMX/MinX/MaxX/AverageX/CountX
LastDate/FirstDate
Calculate
Related
Tabular Functions
Some functions return a table as the output, not a single value, a whole table. The table can
have multiple columns or just a single column depends on the function used. But it would be a table
structure with multiple values in it.
Copy of Customer Table = ALL(DimCustomer)
MAX/MAXX/MAXA
1- MAX DAX Function:
Returns the largest value in a column, or the larger value between two scalar expressions.
MAX (table[column])
When used with a single column, the MAX function internally executes MAXX, without any
performance difference.
Max_Measure = MAX (Orders [Sales])
Equivalent to MAX function
MAXX (
table,
table[column]
)
logical value (Boolean value) Either of the two values true and false that indicate a truth value.
The result is blank in case there are no rows in the table with a non-blank value.
Output=0
When used with a single column, the MIN function internally executes MINX, without any
performance difference.
MIN (table[column])
MINA(<Column>)
When MINA operates with a Boolean data type, it considers TRUE as 1 and FALSE as 0.
Evaluates an expression for each row of a table and returns the smallest value.
The SUM function is an aggregation function, and it calculates the sum of all numbers in a
column.
SUM(<Column>)
TotalSales = SUM('Global-Superstore'[Sales])
SUMX(<table>, <expression>)
Suppose you want to see row wise sum of “Sales” & “Profit” columns together. Here, SUMX helps you
because it is iterator function and perform the operation row wise.
Sales + Profit =SUMX ('Global-Superstore’, 'Global-Superstore'[Sales] + 'Global-Superstore'[Profit])
Get sales of particular year
2013 Sales =SUMX (FILTER ( 'Global-Superstore', Year('Global-Superstore'[Order Date]) = 2013 ),
'Global-Superstore'[Sales])
The column is the numerical column we need to take the average of.
Since the AVERAGE function takes only numerical values for its evaluation, we need to be aware of
non-numerical values and their behaviour. Below are the points to be kept in mind with the non-
numerical values column.
Any column which contains non-numerical values is ignored for aggregation, and the
DAX function returns the blank result.
Logical results like “TRUE” and “FALSE” are ignored from the calculation in Power BI
The empty cells are ignored from the calculation. The cells with 0 are considered for
calculation purposes.
If the column contains logical values or empty cells, those values are ignored and the
rows are not counted.
Cells with the value zero are included and the rows are counted for the divisor.
Whenever there are no rows to aggregate, the function returns a blank. However, if
there are rows, but none of them meet the specified criteria, the function returns 0.
This function takes the specified column as an argument and finds the average of the
values in that column.
Does not support Logical value & Text Value
Cells with the value zero are included.
If Data type is Integer/ Numeric/ Decimal, Average skip the null value.
Returns the average (arithmetic mean) of the values in a column. Handles text and non-numeric
values.
Syntax:
AVERAGEA(<Column>)
Note :
The AVERAGEA function takes a column and averages the numbers, but also handles non-numeric
data types according to the following rules:
The AVERAGEA function takes a column and averages the numbers in it and handles nonnumeric
data types according to the following rules −
Calculates the average (arithmetic mean) of a set of expressions evaluated over a table.
Syntax:
AVERAGEX(<table>,<expression>)
Note:
The function takes a table as its first argument, and an expression as the second argument.
The AVERAGEX function enables you to evaluate expressions for each row of a table, and then take
the resulting set of values and calculate its arithmetic mean.
You cannot include non-numeric or null cells. Both the table and expression arguments are
required.
When there are no rows to aggregate, the function returns a blank. When there are rows, but none
of them meet the specified criteria, then the function returns 0.
Contains:
CONTAINS(<table>, <columnName>, <value>[, <columnName>, <value>]…)
Similarly
NOT CONTAINS (Customer, Customer [Continent], Store [Continent], Customer [State], Store [State],
CONTAINSROW function
The number of scalarExprN must match the number of columns in table Expr.
NOT IN is not an operator in DAX. To perform the logical negation of the IN operator, put
NOT in front of the entire expression.
CONTAINSSTRING
A value of TRUE if the string WithinText contains the string FindText – the comparison is not case-
sensitive.
CONTAINSSTRING(<within_text>, <find_text>)
Wildcard Characters
* Represents zero or more characters bl* finds bl, black, blue, and blob
[] Represents any single character within the brackets h[oa]t finds hot and hat, but not hit
! Represents any character not in the brackets h[!oa]t finds hit, but not hot and hat
- Represents any single character within the specified range c[a-b]t finds cat and cbt
# Represents any single numeric character 2#5 finds 205, 215, 225, 235, 245, 255, 265,
275, 285, and 295
CONTAINSSTRINGEXACT ()
A value of TRUE if the string WithinText contains the string FindText – the comparison is case-
sensitive.
The CONTAINSSTRINGEXACT function does not accept wildcards to perform the search
TABLE LEVEL FUNCTIONS:
1. Selectcolumns
Returns a table with selected columns from the table and new columns specified by the DAX
expressions.
Country, State
IND, JK
IND, MH
IND, WB
USA, CA
USA, WA
/* SELECTCOLUMNS is an iterator that returns a selection of columns / expressions evaluated in the
row context during the iteration over its first parameter. */
SELECTCOLUMNS (
TOPN (10, 'Product’),
"Product Category", 'Product'[Category],
"Product Subcategory", 'Product'[Subcategory],
"Product Color", 'Product'[Color],
"Product Name", 'Product'[Product Name],
"#Products", CALCULATE (COUNTROWS (‘Product’)),
"Sales", [Sales Amount]
)
2. ADDCOLUMNS
Returns a table with new columns specified by the DAX expressions.
ADDCOLUMNS(<table>, <name>, <expression> [, <name>, <expression>] …)
ADDCOLUMNS (ProductCategory,
“Internet Sales", SUMX(RELATEDTABLE(InternetSales_USD), InternetSales_USD[SalesAmount_USD])
, "Reseller Sales", SUMX(RELATEDTABLE(ResellerSales_USD), ResellerSales_USD[SalesAmount_USD])
)
/* ADDCOLUMNS is an iterator that returns its first argument after adding the column specified.
New columns are computed in the row context of ADDCOLUMNS, you need to invoke context
transition to generate a filter context, if needed. */
ADDCOLUMNS (
VALUES (‘Date'[Calendar Year]),
"@Year Number”, INT (RIGHT (‘Date'[Calendar Year], 4)),
"@Amount”, [Sales Amount], Please identify the
"@Quantity Wrong”, SUM (Sales [Quantity]), difference between two
"@Quantity Correct", CALCULATE (SUM (Sales [Quantity])) highlighted rows and
) check the output also.
3. CROSSJOIN
Returns a table that is a crossjoin of the specified tables.
CROSSJOIN(<table>, <table> [, <table>] …)
ADDCOLUMNS (
CROSSJOIN (VALUES ('Product'[Color]), VALUES ('Product'[Category])),
"#Prods", CALCULATE (COUNTROWS (‘Product’))
)
4. DATATABLE
orders2 = DATATABLE ("ID”, INTEGER, “Customer Name”, STRING,"CITY”, STRING, “sales”, DOUBLE,
{orders ['ROW ID']}) -----------ERROR
5. VALUES
When the input parameter is a column name, returns a one-column table that contains the
distinct values from the specified column. Duplicate values are removed and only unique
values are returned. A BLANK value can be added (considered as row).
When a table name is given, returns a table with the same columns and all the rows of the
table (including duplicates) with the additional blank row caused by an invalid relationship if
present.
6. DISTINCT
Returns a one-column table that contains the distinct values from the specified column. In
other words, duplicate values are removed and only unique values are returned. (a blank value
also considers). A column of unique values.
Returns a table by removing duplicate rows from another table or expression. A table
containing only distinct rows.
col_distinct = COUNTROWS(DISTINCT('Fact'[Fact]))
col_values = COUNTROWS(VALUES('Fact'[Fact]))
col_distinct_dim = COUNTROWS (DISTINCT (Dim [Dim]))
col_values_dim = COUNTROWS (VALUES (Dim [Dim]))
Dim Fact
A A
B B
A
B
C
D
D
C
Dim Fact
A A
B B
C A
B
C
D
D
C
Dim Fact
A A
B B
C A
B
C
C
Remember: in above 3 tables, blank cell in Dim table represents, other than primary key column
values.
I have two tables (model), a dimension table (or master) and a facts table (or detail),
related one-to-many.
I have created two table visuals, each one showing the fields of each model table.
When I select a row in the table visual for dimensions, only the related rows in the table
visuals for facts are showed. That is the normal behaviour of Power Bi.
But when I select a row (or rows) in the table visual for facts, the table visuals for
dimension is not filtered, showing only the related ones.
One – Many
You have multiple records for each value in the joining field between tables, for both tables. If you
think about it for a second, you can see that this scenario happens when you have tables that are
related to each other with no shared dimension in between! Let’s check one example; Let’s say I
have a Fact Inventory table and a Fact Sales table. They both have multiple records per product. and
I want to connect them together using the Product ID. this has to be a many-to-many relationship
because there is no product ID field which has unique values in it.
One to One
A one-to-one relationship means both columns contain unique values. This cardinality type isn't
common, and it likely represents a suboptimal model design because of the storage of redundant
data.
A one-to-one relationship happens only in one scenario when you have unique values in both tables
per column. An example of such scenario is when you have a Titles and a Titles Details table! They
both have one row per title.
When you have a one-to-one relationship between two tables, they are a good candidate to be
combined with each other using Merge in Power Query. Because both tables have the same number
of rows most of the time
VISUALISATION USING DIM VS FACT:
Fact table
Dimension is a table, which adds some additional info to a fact table information.
For example, to ID product 11 it provides the info about price (91) and name (Cream).
Power BI
In reports generated from data models we normally use columns from both dimensions and fact
tables.
Now let’s define which columns are connected. These connections are called "relationships" and can
be simply done by dragging of column from one table to another. These columns are called "keys".
The key column must have unique values in dimension, but usually it has repeated values in a fact
table.
Reports
What does it mean for report creation (or Pivot tables in Power Pivot)?
Usually, the columns from fact tables take place in fields like "Values" - they contain
numbers we want to calculate.
Columns from dimensions usually belong to fields for grouping - like "Rows", "X Axis",
"Category"...
applying a filter on a column of a Dimension table should produce the same result as of applying the
same filter to a related column in the Fact table.
7. UNION
Return value:
A table that contains all the rows from each of the two table expressions. (allowing
duplicate rows also).
Important Points:
8. INTERSECT
INTERSECT(<table_expression1>, <table_expression2>)
A table that contains all the rows in table_expression1 that are also in table_expression2.
Remarks
Intersect is not commutative. In general, intersect (T1, T2) will have a different result set
than Intersect (T2, T1).
Duplicate rows are retained. If a row appears in table_expression1 and
table_expression2, it and all duplicates in table_expression_1 are included in the result
set.
The column names will match the column names in table_expression1.
Columns are compared based on positioning, and data comparison with no type
coercion.
Return value
A table that contains the rows of one table minus all the rows of another table.
Remarks
If a row appears at all in both tables, it and its duplicates are not present in the result
set. If a row appears in only table_expression1, it and its duplicates will appear in the
result set.
The column names will match the column names in table_expression1.
The two tables must have the same number of columns.
Columns are compared based on positioning, and data comparison with no type
coercion.
The set of rows returned depends on the order of the two expressions.
10. FILTERS VS FILTER
Returns a table of the filter values applied directly to the specified column. (DISTINCT COLUMN
VALUES)
FILTERS VALUES
CALCULATETABLE ( CALCULATETABLE (
FILTERS (‘Product'[Category]), VALUES (‘Product'[Category]),
'Product'[Category] = "Audio" 'Product'[Category] = "Audio"
) )
CALCULATETABLE ( CALCULATETABLE (
FILTERS (‘Product'[Category]), VALUES (‘Product'[Category]),
'Product'[Category] IN {“Audio", "Computers”} 'Product'[Category] IN {“Audio", "Computers”}
) )
CALCULATETABLE ( CALCULATETABLE (
FILTERS (‘Product'[Category]), VALUES (‘Product'[Category]),
'Product'[Category] IN {“Audio", "abc”} 'Product'[Category] IN {“Audio", "abc”}
) )
CALCULATETABLE ( CALCULATETABLE (
FILTERS (‘Product'[Category]), VALUES (‘Product'[Category]),
'Product'[Category] IN {"abc”} 'Product'[Category] IN {"abc”}
) )
NO ROWS RETURN NO ROWS RETURN
CALCULATETABLE ( CALCULATETABLE (
FILTERS ( 'Product'[Category] ), VALUES ( 'Product'[Category] ),
'Product'[Color] = "Azure" 'Product'[Color] = "Azure"
) )
Color value filter having no effect on FILTERS Color value filter effect on VALUES data.
data.
-- Table filter include columns used in FILTERS -- Table filter include columns used in VALUES
CALCULATETABLE ( CALCULATETABLE (
FILTERS (‘Product'[Category]), VALUES (‘Product'[Category]),
FILTER (‘Product', 'Product'[Color] = "Azure”) FILTER (‘Product', 'Product'[Color] = "Azure”)
) )
ROW:
Row DAX function returns a table with a single row containing values that result from the
expressions given to each column.
Table = ROW ("Total Sales", SUM (Orders [Sales]),"Total Profit", SUM (Orders [Profit]),"Total
Discount", SUM (Orders [Discount]))
RELATED VS RELATEDTABLE
RELATED function is used to get the parent table column name into child table.
Sub_category_c=RELATED(Product[‘sub_category’])
ID1 Support
Name
1 A
2 B
3 C
ID2
1 S1
2 S2
4 S4
GenerateSeries
Returns a table with one column, populated with sequential values from start to end.
GENERATESERIES(<startValue>, <endValue>[, <incrementValue>])
Return value
A single column table containing the values of an arithmetic series. The name of the
column is Value.
Remarks
When endValue is less than startValue, an empty table is returned.
incrementValue must be a positive value.
The sequence stops at the last value that is less than or equal to endValue.
Table Constructor:
Returns a table of one or more columns.
{<scalarExpr1>, <scalarExpr2>, …} //returns a table of a single column.
{(<scalarExpr1>, <scalarExpr2>, …), (<scalarExpr1>, <scalarExpr2>, …), …} // returns a table of
one or more columns.
Summarizecolumns:
It is also like group by functionality like sql.
Summarizecolumns (column name1, column name2, column name3…, FILTER expression,
“new column name”, expression, “new column name”, expression...)
Return Value
A table which includes the combinations of values from the supplied columns, based on the
grouping specified.
Only rows for which at least one of the supplied expressions return a non-blank value are
included in the table returned.
If all expressions evaluate to BLANK/NULL for a row, that row is not included in the table
returned.
SUMMARIZE:
Returns a summary table for the requested totals over a set of groups.
SUMMARIZE (<table>, <groupBy_columnName>, [<groupBy_columnName>] …,
[<name>, <expression>] …)
Data Lineage is a key part of Data Governance within Power BI, showing you which data
sources are used by which datasets, and then by which reports.
It enables you to see the upstream and downstream path of your data.
CROSSFILTER:
Table A
Sales_id
Prod_id
Table C
Table B
Prod_id
Sales_id
Quantity
Sales_ref
We want Table B sales_ref wise Table C Quantity. In this Table B and Table C having not relations
ship directly. In this case we use CROSSFILTER mechanisum.
Way 1: you build “BOTH” (bi-directional) Relationship between Table B (filtering column
containing table) and Table A. (master table).
CROSSFILTER (many relationship filtering column table names, One relation table)
DimProduct DimSalesTerritory
FactInternetSales
Remember:
1. In one to many relationships, for date columns participates in relationship, we lose hierarchy
in many side columns.
2. One-to-One, Many-to-Many relationships, which table column we drag into another table,
that column date hierarchy loose.
3. When date filed is related to another non-date field, loses date hierarchy in many sides.
Userelationship:
Orders table
DimDate table
Order_date
Date
Sales_date
Due_date
sales value ship date_m = CALCULATE (sum (Orders [Sales]), USERELATIONSHIP (Orders [Ship Date],
DimDate [Date]))
Here filter accepting only given table column names only. If you want you can use
Parent (DIM) table column names with RELATED function. (filter works on row context)
Here filter accepting all table columns. (HERE no need of RELATED function while
accessing DIM Tables). (filter works on Filter Context )
FILTER VS CALCULATEDTABLE DIFF:
While the resulting tables are the same, the way the tables are created is completely different.
FILTER first saw the all products table, then ran the "is the product color red" test for each row of
this table, returning the rows that passed the test as a table. The products table has a total of 2517
rows, iterated each row in the same table 2517 times, returning 99 rows that passed the test.
CALCULATETABLE, on the other hand, first found the products with red color, while doing this, it did
not iterate through the rows, it worked directly on the values in the color column, then returned the
table with these products.
According to the examples above, the first difference between the two functions isFILTER being an
iterator. CALCULATETABLE is not an iterator.
FILTER first reads the first parameter (table) and then returns rows from this table that match the
conditions.
On the other hand, CALCULATETABLE first applies the condition and then runs the first parameter
accordingly.
It returned 9994 and the number returned is incorrect. This number is not the number of Furniture
category products, but the number of all category products!
In the first expression we wrote with CALCULATETABLE, condition is running first! Therefore, there
are only Furniture products in the table that both ADDCOLUMNS and VALUES see. It even -according
to this example- VALUES (Orders [Category]) sees the single line “Furniture” table. That's why it
calculates 2121 without the need for a context transition.
In the version we wrote with FILTER, before ADDCOLUMNS and group VALUES are working. The
category column that VALUES sees has all categories, including Furniture. When he counts the
products under all categories, he finds 9994. FILTER's condition only takes effect after this calculation
has been made. It remains Furniture in category. However, since we did not make a "context
transition" in the formula we wrote, it continues to count all the products. For this statement to
work correctly, we need to call COUNTROWS with CALCULATE.
Remember:
I have added one duplicate record in Orders table only I update ID column value. (in 2011
Jan month).
In the Max Sales calculation, [total Sales_m] measure calculate based on each row by row of
Orders table records of after apply year, month filter data. We get below Order data with
Total sales.
Using the above table, we get maximum value of total sales value. (that’s why we are getting rowing
value 23164.38, not getting 46328.76 value.)
IV. Maxx function work on above table total sales column value.
ISBLANK () VS BLANK ()
Remember:
When we import excel file into PowerBI, all empty string columns are taken as null.
When we import sql server database table data into PowerBI, empty string columns are
taken as empty and NULL column values are taken as null.
OR
OR
1. The first argument, i.e., Table, accepts a physical or a virtual table to Filter.
A physical table can be seen in the data model.
A virtual table is the one created on the fly.
2. The second argument, i.e. Condition accepts a logical test that is performed in each row of the
table.
All rows that satisfy the condition, i.e. return TRUE are kept while other rows are removed.
Keep in mind the condition must return a True or False output else it stands invalid.
FILTER Function used on a Virtual Table
Sales was a physical table present in the Data Model, let’s see if we can apply the FILTER function to
a table that doesn’t physically exist i.e. a Virtual Table.
Let’s solve this Question – Get a table of dates where the sales amount is >= $50000. Consider this
DAX for creating a Table.
The DAX syntax is made up of different elements and when combined results in the following
formula.
SUM
Let’s start with SUM. Most of you know what SUM is, if you’ve ever used Excel or some
other software programs, SUM comes quite naturally. We understand SUM adds up all the values in
a column, and because of this the SUM syntax requires a column as input.
SUM(<column>)
In order to see how this function operates, let’s create a new measure. Let’s say that we want to
calculate the value of all our individual items sold. We will call our measure SUM and we’ll SUM the
column ‘Total Sales’ from our ‘Sales’ table. SUM is going to look at the ‘Total Sales’ column in the
‘Sales’ table and sum all the values together.
Let’s use a matrix visual to display the measure ‘SUM’ by ‘ITEMNAME’. To do this, we add
‘ITEMNAME’ as the row value and ‘SUM’ as our values in Power BI. Here we can see that SUM does
exactly what we expect it to do. It will sum the values for each ‘ITEMNAME’ in the table together and
return us a Total at the bottom. This total is the Total value for ‘SUM’ of all the ‘ITEMNAMES’.
SUMX
Let’s create a new measure now to see how the function SUMX operates. The first notable
difference for SUMX is that you need to provide the table name and an expression, so SUMX returns
the sum of an expression evaluated for each row in the table. The term <table> contains the rows for
which the expression will be evaluated, and the term <expression> evaluate each row of the table
SUMX(<table>, <expression>)
In other words, let’s say we want to determine the Total sales for each unit, we will have to choose
the ‘Sales’ table, and, in the ‘Sales’ table, we have two values, quantity of units sold ‘QTYNET’ and
the unit price ‘Unit Price’ that must be multiplied to determine the Total sales for each unit.
Let’s add the measure to our canvas and immediately we see it does the same thing, it sums the
Total sales for each item.
So, the difference here is that SUMX goes to each row in the table and it says multiply the quantity
by the unit price and then give us the Total sales amount and does that iteratively for each row in
the table and once it reaches the bottom it does a sum and adds up all those values together. SUM
on the other hand basically multiplies the two values together. So, a good comparative example is
where SUM would be ten times ten and SUMX would be 10 + 10 + 10 + 10, 10 times. Ultimately, they
get to the same amount but that’s the difference in how these two functions operate. Because of
that SUMX is not as efficient as SUM, but depending on your situation, it may give you the ability to
do a little more.
CALCULATE
If you are new to DAX, the SUMX and SUM measures that we just created can be used in other DAX
calculations. What I mean is that you can use one measure within another measure, and we will do
that now when we get to the CALCULATE function. The CALCULATE function requires an
<expression> and a comma separated list of Booleans (true or false statements) expressions,
defining one or more <filters>, which is optional to fill in.
In this expression you can do one of two things when you want to do a SUM of the Sales and then
apply a filter. You will be able to use either an existing created measure such as the SUM or SUMX
that we have just created, or alternatively you will need to apply the SUM or SUMX function in the
expression referencing the table ‘Sales’ and column ‘Total Sales’ as below.
You could do as in the above formula, but best practice for DAX would be to build on top of the
previous measures that you have created. In this case, I am going to use the SUM measure that I
have already obtained and apply a filter to that measure. So, for example, let’s say that we want a
table like the one that we have created, but we don’t want to see the values for all items. We want
to filter this table by a customer name. In order to filter by the customer name ‘ACME Plumbing’, we
take the column ‘CUSTOMERNAME’ from the ‘Customers’ table where it equals ‘ACME Plumbing’.
Another example would be to say that we want to calculate the Total Sales for two companies called
‘ACME Plumbing’ and ‘Custom Comfort’. This can be done in the same way as we did previously
when calculating the Total Sales for ‘ACME Plumbing’. Let’s do this same measure now for ‘Custom
Comfort’.
Now, we can add ‘ACME Plumbing’ and ‘Custom Comfort’ to one table.
Wow, we can see what’s happening here. This table shows the combined sales and items sold for
both companies ‘ACME Plumbing’ and ‘Custom Comfort’ above.
Congratulations! This is the first step in the process of becoming a master in DAX. It is a journey not a
destination, so stick with us and we will continue showing you how these calculations work.
If we look at the Sales table from the Data view pane, we can see what it has done is to filter on the
CUSTOMERNAME for each row in the table, which is the outer filter context.
CASE 2:
Let’s do another measure. I want to do the sales amount where the sales quantity is greater than
100. For ease of reference, I’m going to call it ‘Sales quantity > than 100’.
I want to do a CALCULATE of the sales measure we created earlier called ‘Sales’ where the sales
quantity is greater than 100.
If we look at the Sales table from the Data view pane, we can see what it has done is to filter on the
CUSTOMERNAME for each row in the table (ACME Plumbing for example), which is the outer filter
context.
Then it goes to the inner filter context (inside the DAX CALCULATE function) where it takes the
quantity column and applies a filter where the sales quantity is greater than 100.
It then sums up the total sales together to give us an answer for each of the CUSTOMERNAMEs.
CASE 3:
I want to do a similar calculation than before where I’m going to calculate the total sales where the
quantity again is greater than 100. But this time I’m going to use SUMX instead of SUM, so let’s see
how that works.
Start with CALCULATE and use a SUMX of the ‘Sales’ table and multiply the Sales [Unit Price] by the
Sales [QTYNET] (the Quantity) and then finally let’s include a filter where the Sales [QTYNET] > 100.
Format to British Pound and let’s put it on the canvas.
Okay great so it seems like it does the same thing, right?! We can see that the answer from
our SUM and from the SUMX is the same. The difference with SUMX and SUM is in the way it
evaluates.
So for each row where it finds a quantity larger than 100, it will calculate the Sales[Unit
Price] * Sales[QTYNET] and store that value, and once it has reached the bottom of our table, it will
SUM all those values together and return the answer.
CASE 4:
let’s do another measure where the sales quantity is greater than 100, but this time I want to add a
few other interesting functions into our calculation.
Let’s do a CALCULATE, where we SUM the Sales [Total Sales] but in this case let’s add a FILTER
function and the ALL function.
So, we’re gonna FILTER ALL values from the Sales table where the Sales [QTYNET] is greater than
100. Let’s call the measure Sales Quantity > 100 equiv (for equivalent of the previous measure).
The FILTER function as we know will return a filtered table, and the ALL function will force ignore all
outside filter context and apply the expression on ALL items where Sales [QTYNET] is greater than
100.
If we add the measure to our canvas, we can see it returns the same answer still. If we look at our
two measures we have the first one which is just a normal CALCULATE where we added a filter
where the quantity is larger than 100.
For our second measure, we used we did the same thing but instead of SUM we used SUMX to get
us the same value and in the last one we’ve now said CALCULATE the SUM of Sales[Total Sales] but
before we do that FILTER the Sales table and return ALL values irrespective of our outside filter
context where it will force the calculation to return the entire table and then filter it where the Sales
quantity is greater than 100.
Okay great so we have three separate calculations which are different yet provides us the exact
same answer and they get to that answer in slightly different way. Let’s use another few examples
and that I want to use just to explain how and these other calculations will work if we actually apply
an outer filter context.
For the first measure I want to do the total sales for the customer called “The Courtyard”.
So, I want to filter all cells with a customer name that is equal to “The Courtyard”.
Start with a SUMX and add the FILTER function of the Sales table and then also apply the RELATED
function where it fetches the value from a related table (Called Customers) and I want to go and find
the customer name from customers table where it’s equal to “The Courtyard”.
Finally, we want to be able to do the Sales [Unit Price] multiplied by the Sales [QTYNET].
Drag it onto the canvas and we can see that now it has returned a value, but only for “The
Courtyard”.
Note: Remember that SUMX is an iterator, so it goes through each line in the table and CALCULATES
the Sales [Unit Price] multiplied by the Sales [QTYNET], but before it does so it finds the “The
Courtyard” value from the RELATED Customers table, and applies the FILTER in the CUSTOMERNAME
column.
Note that RELATED can only work if there is a relationship between the Sales and Customers table.
Let’s do another measure, but this time we’ll use CALCULATE with the [Sales] measure we already
created previously.
Remember that when we use CALCULATE we can either do a SUM of the Sales [Total Sales] or use an
existing measure called [Sales] which already calculates a SUM (Sales [Total Sales].
To continue with our formula, let’s CALCULATE the [Sales] and we want to filter the
CUSTOMERNAME from the Customers table where the value is equal to “The Courtyard”.
Finally lets formatted to British Pound and add it to our canvas.
It seems like it’s given the same answer as with our previously used RELATED function inside of the
Sales (The Courtyard) measure.
Before we test adding an outer filter context, I would like to add one more measure.
So as an introduction to the ALL and FILTER functions and how they work with the CALCULATE
function, lets create a measure called ‘Sales (The Courtyard) CALCULATE_FILTER_ALL’.
For this measure I want to CALCULATE again of the [Sales] measure, let’s use the FILTER function of
ALL items in the Sales [CUSTOMERNAME] column and finally filter the Sales [CUSTOMERNAME] table
to only include items that belong to “The Courtyard”.
So, before it CALCULATEs the [Sales] measure, it first applies the FILTER context. It starts with the
FILTER function, returns ALL values from the Sales [CUSTOMERNAME] column (This actually returns a
unique list of the values from the Sales [CUSTOMERNAME] column) and then filters the column
values to only include “The Courtyard”.
Then it CALCULATES the [Sales] measure and returns the answer. Again lets add it to the canvas and
format to British Pound.
Interesting, so it returns a value for every single customer but which is equal to “The Courtyard”. In
this case it actually forces it with ALL and the internal filter context to ignore the outer filter context.