Is it possible to have a variable that's only calculated whenever a filter is applied? - dax

I'm trying to optimize a measure, and after analyzing it I found that the problem comes from the fact that part of it is calculated on every row when it only needs to be calculated once when a certain filter is applied.
Here's the measure :
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
FILTER (
Sales,
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)
In this case, LastPeriod will be calculated over and over, whereas we only need it to be calculated once when a filter is applied on Time.
Is there any way to store this information somewhere so that it doesn't have to make superfluous calculations ?

Try this 2 Codes, and let me know If one or both of them are any faster. Instead of iterating (or scanning ) a full table, you only iterate the columns you need in a filter argument. Like this:
Version-1
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
FILTER (
ALL ( Sales[ClientLastOrder], Sales[ClientEntry] ),
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)
Version-2
Effectif :=
VAR LastPeriod =
MAX ( 'Time'[Period] )
RETURN
CALCULATE (
DISTINCTCOUNT ( 'Sales'[ClientID] ),
CALCULATETABLE (
SUMMARIZE ( Sales, Sales[ClientLastOrder], Sales[ClientEntry] ),
OR (
LastPeriod - Sales[ClientLastOrder] < 4,
LastPeriod - Sales[ClientEntry] < 4
)
)
)

It is hard to be confident without any data sample, but I guess that this formula of LastPeriod calculating may help you:
VAR LastPeriod =
CALCULATE(
MAX ( 'Time'[Period] ),
ALL('Sales')
)
Also you may check such function as ALLSELECTED(). It may fit you more.

Related

Time based Calculation groups - apply year to date to a yearly comparison

The workfile is available here
I wish to conduct time-based analysis on my datas.
For this purpose, I have created 2 calculation groups.
Year comparison that enables me to deal with relative yearly data :
N :=
VAR lv_MAX_YEAR =
[RELATIVE_MAX_YEAR] - 0
RETURN
CALCULATE (
SELECTEDMEASURE() ,
dim_CALENDAR[Year] = lv_MAX_YEAR
)
N-1 :=
VAR lv_MAX_YEAR =
[RELATIVE_MAX_YEAR] - 1
RETURN
CALCULATE (
SELECTEDMEASURE() ,
dim_CALENDAR[Year] = lv_MAX_YEAR
)
N/N-1 Evolution :=
VAR N = CALCULATE( SELECTEDMEASURE() , 'Year comparison'[Year comparison] = "N" )
VAR N_1 = CALCULATE( SELECTEDMEASURE() , 'Year comparison'[Year comparison] = "N-1" )
RETURN
N - N_1
Works fine for me with the expeced behaviour : N is by default the current year (max year in my calendar table), but if I filter on a given year, N becomes that one.
and Relative Period allows me to compare Sales by the number of passed day from the beginning of the year :
[MAX_YEAR_DAY] :=
VAR lv_MAX_YEAR =
CALCULATE (
MAX ( dim_CALENDAR[Year] ) ,
ALL ( dim_CALENDAR[Year] )
)
RETURN
CALCULATE (
MAX ( dim_CALENDAR[Year_day] ) ,
dim_CALENDAR[Year] = lv_MAX_YEAR
)
Year To Max Year_day :=
VAR lv_MAX_YEAR_DAY =
[MAX_YEAR_DAY]
RETURN
CALCULATE (
SELECTEDMEASURE () ,
dim_CALENDAR[YEAR_DAY] <= lv_MAX_YEAR_DAY
)
So far it's a partial success :
my grand totals seem correct ;
but my monthly details don't ;
and my yearly comparison gets busted when it's activated.
How can I use both calculation groups simultaneously?

PBI Measure as a Value in Matrix Visual

I appreciate some help with the below problem.
I have the table
Month
Line
Amount
Jan
ST
20
Jan
AB
10
Jan
AC
2
Jan
AG
15
Feb
ST
40
Feb
AB
20
Feb
AC
4
Feb
AG
8
Mar
ST
65
Mar
AB
5
Mar
AC
6
Mar
AG
2
and I want a Matrix
Jan
Feb
Mar
AB
50.00%
50.00%
7.69%
AC
10.00%
10.00%
9.23%
AG
75.00%
20.00%
3.08%
The Value of the Matrix is a Mesure
(%) Amount ST =
SWITCH (
TRUE (),
SELECTEDVALUE ( table1[Line] ) = "AB",
DIVIDE (
SUM ( table1[Amount] ),
CALCULATE ( SUM ( table1[Amount] ), FILTER ( 'table1', table1[Line] = "ST" ) )
),
SELECTEDVALUE ( table1[Line] ) = "AC",
DIVIDE (
SUM ( table1[Amount] ),
CALCULATE ( SUM ( table1[Amount] ), FILTER ( 'table1', table1[Line] = "ST" ) )
),
SELECTEDVALUE ( table1[Line] ) = "AG", DIVIDE ( SUM ( table1[Amount] ), 4 ),
SUM ( table1[Amount] )
)
The measure works fine for AG, to test it I used in the denominator the number 4, but when I added the calculate function to filter by ST I didn't see it in the visual ???
Any ideas
Thank you
OJ
I'm not sure what are you calculating. From your measure, is this is what are you looking for?
DAX Calculation
(%) Amount ST =
VAR STAmount =
CALCULATE ( SUM ( table1[Amount] ), table1[Line] = "ST" )
RETURN
SWITCH (
TRUE (),
SELECTEDVALUE ( table1[Line] ) = "AB", DIVIDE ( SUM ( table1[Amount] ), STAmount ),
SELECTEDVALUE ( table1[Line] ) = "AC", DIVIDE ( SUM ( table1[Amount] ), STAmount ),
SELECTEDVALUE ( table1[Line] ) = "AG", DIVIDE ( SUM ( table1[Amount] ), STAmount ),
SUM ( table1[Amount] )
)
Output

Getting the total value in all the rows

I'm using the calculation below to calculate the sum of the amount for accounts >= 200
And the problem I have is when I visualize Account with Account total with excel, it gives me the total amount in all accounts.
How can I solve this?`
Account total:= CALCULATE(SUM('Table'[amount]),'Table'[Type]= "ABC",'Table'[account] >=200)
#Jos is mostly correct but there are some small inaccuracies.
This code
CALCULATE (
SUM ( 'Table'[amount] ),
'Table'[Type] = "ABC",
'Table'[account] >= 200
)
is equivalent to
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table'[Type] ), 'Table'[Type] = "ABC" ),
FILTER ( ALL ( 'Table'[account] ), 'Table'[account] >= 200 )
)
not
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table' ), 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
In particular, if you had a filter on, say, 'Table'[Category], this would be preserved in the former but not in the latter since ALL ( 'Table' ) removes filters on all of the columns, not just [Type] and [account].
I propose the following two nearly equivalent solutions, which are slightly more computationally efficient than filtering an entire table:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( VALUES ( 'Table'[Type] ), 'Table'[Type] = "ABC" ),
FILTER ( VALUES ( 'Table'[account] ), 'Table'[account] >= 200 )
)
or
CALCULATE (
SUM ( 'Table'[amount] ),
KEEPFILTERS ( 'Table'[Type] = "ABC" ),
KEEPFILTERS ( 'Table'[account] >= 200 )
)
More on KEEPFILTERS: https://www.sqlbi.com/articles/using-keepfilters-in-dax/
You should be using:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( 'Table', 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
The difference is that your current formula is equivalent to:
CALCULATE (
SUM ( 'Table'[amount] ),
FILTER ( ALL ( 'Table' ), 'Table'[Type] = "ABC" && 'Table'[account] >= 200 )
)
i.e. identical to that which I give apart from the crucial difference that it applies an (in your case implicit) ALL to the table prior to filtering. This implicit ALL will override any filters you may be applying externally.

Using SELECTEDVALUE with PowerPivot instead of Power BI

I moved a report from Power BI to Power Pivot, but the formula of SELECTEDVALUE does not exist in Power Pivot.
Can you help correct to a function that works in Power Pivot?
las_val =
VAR y =
SELECTEDVALUE ( DateTime[Gasday] )
RETURN
CALCULATE (
HEML_TTF_PRICE_V[TTF_DA_WE],
TOPN (
1,
FILTER (
ALLSELECTED ( DateTime[Gasday] ),
DateTime[Gasday] <= y
&& NOT ( ISBLANK ( HEML_TTF_PRICE_V[TTF_DA_WE] ) )
),
DateTime[Gasday], DESC
)
)
SELECTEDVALUE is a newer function that's a shortcut for
IF ( HASONEVALUE ( DateTime[GasDay] ), VALUES ( DateTime[GasDay] ) )

DAX divide each row value with the result of a cumulative sum

I have two tables that contain the number of users of two types (see picture).
I have created a measure that computes the cumulative sum of the number of Users2
TotalUsers2 =
CALCULATE (
SUM ( Users_2[Users_2] ),
FILTER (
ALLSELECTED ( Users_2 ),
'Users_2'[Year_month] <= MAX ( 'Users_2'[Year_month] )
)
)
I would like to divide each row of table 1 with the rows of TotalUsers2.
For example, for 2019_01, I have 10 Users1 and 1000 in the totalUsers2, I want to obtain the 10/1000 * 100 value.
For 2019_02, 20/1500 * 100, for 2019_03, 30/1700 * 100, and so on.
Just put that measure in the denominators, except you'll need to use Users_1[Year_month] instead of Users_2[Year_month] for the MAX.
TotalUsers2 =
DIVIDE (
SUM ( Users_1[Users_1] ),
CALCULATE (
SUM ( Users_2[Users_2] ),
FILTER (
ALLSELECTED ( Users_2 ),
Users_2[Year_month] <= MAX ( Users_1[Year_month] )
)
)
)

Resources