Restore original filter context in DAX formula - ssas

I have a data model with a table called Transactions (below), and TranDate which is the date dimension.
I have a measure to calculate the opening balance for the first date that is visible in the pivot table.
Op Bal First Selected :=
VAR MinDate = CALCULATE (
MIN ( TranDates[Tran Date] ),
ALLSELECTED ( TranDates )
)
RETURN
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL ( TranDates ),
TranDates[Tran Date] < MinDate
)
)
If I deselect Jan-16, I get the desired result below:
However, the measure only works in Excel 2016 and not Excel 2013, because variables are not supported in Excel 2013. If I replace the MinDate variable with the DAX expression, then the measure will return blanks because ALLSELECTED restores the context in the FILTER() function and not the context in the CALCULATE() function (i.e. MinDate is 1-Jan instead of 1-Feb).
Is there an equivalent DAX formula that works in Excel 2013 / SSAS 2014 (i.e. without using variables)?

After lots of trial and errors, here's the measure I defined:
Op Bal First Selected:=
MINX
(
ADDCOLUMNS (
ADDCOLUMNS
(
SUMMARIZE (
ALL(Transactions),
Transactions[Tran Date]
),
"MinDate",
CALCULATE (
MIN ( Transactions[Tran Date] ),
ALLSELECTED()
)
),
"Op Bal First Selected Calc",
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL( Transactions ),
Transactions[Tran Date] < [MinDate]
)
)
),
[Op Bal First Selected Calc]
)
I used ALL() in the inner context so that the original filter context (i.e. pivot table selection) is preserved in the context just outside of ALLSELECTED().
If you want to use the TranDate table as the filter, you can define it as follows:
Op Bal First Selected:=
MINX
(
ADDCOLUMNS (
ADDCOLUMNS
(
SUMMARIZE (
ALLSELECTED(TranDates),
TranDates[Tran Date]
),
"MinDate",
CALCULATE (
MIN ( TranDates[Tran Date] )
)
),
"Op Bal First Selected Calc",
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL( TranDates ),
TranDates[Tran Date] < [MinDate]
)
)
),
[Op Bal First Selected Calc]
)

Related

Getting error when Calculating the Sum of premium values using DAX on a slowly changing dimension

Using DAX - I need to calculate the total premium amount for policies with a certain status - using a slowly changing dimension as a source.
This is something that's running within SSAS tabular model.
The solution has two tables - dim_date (which is a calendar table) and a Dim_contract (which have all my policies listed)
The Dim_Contract table is a slowly changing dimension.
The table format:
DW_ContractID DW_EffectiveFromDate contract_number actual_recurring_collection ContractStatusTLA
-2145825896 22 August 2018 4303140 80 PIN
-2145627139 26 September 2018 4303140 80 INF
-2145428382 09 October 2018 4303140 80 Can
-2145229625 21 August 2018 4303142 100 PIN
-2145030868 22 September 2018 4303142 100 NTU
-2144832111 02 September 2018 4303999 50 PIN
-2144633354 03 September 2018 4303999 50 INF
I've done a calculation to count the policies - which work 100%.
With this calc, we count the number of policies for each time period. (depending what the user selects)
Example - if we want to count the number of policies as at the end of September per status we should get:
INF: 2 (This is counting policy numbers 4303140 and 4303999 as their last status is INF)
CAN: 0
NTU: 1
The code used to do the counts:
PolicyCount_NTU :=
IF (
MIN ( DIM_Date[Date] )
>= CALCULATE ( MIN ( DIM_Contract[DW_EffectiveFromDate] ), ALL ( DIM_Contract ) ),
IF (
MIN ( DIM_Date[Date] )
<= CALCULATE ( MAX ( DIM_Contract[DW_EffectiveFromDate] ), ALL ( DIM_Contract ) ),
CALCULATE (
COUNTROWS (
FILTER (
DIM_Contract,
DIM_Contract[DW_ContractID]
= CALCULATE (
MAX ( DIM_Contract[DW_ContractID] ),
ALL ( DIM_Contract ),
DIM_Contract[contract_number] = EARLIER ( DIM_Contract[contract_number] ),
( DIM_Contract[DW_EffectiveFromDate] ) <= VALUES ( DIM_Date[Date] )
)
)
),
LASTDATE ( DIM_Date[Date] ),
DIM_Contract[ContractStatusTLA] = "NTU"
)
)
)
The problem comes in with the calc to get the sum of the amounts...
I used this code:
PolicyAPI_NTU :=
IF (
MIN ( DIM_Date[Date] )
>= CALCULATE ( MIN ( DIM_Contract[DW_EffectiveFromDate] ), ALL ( DIM_Contract ) ),
IF (
MIN ( DIM_Date[Date] )
<= CALCULATE ( MAX ( DIM_Contract[DW_EffectiveFromDate] ), ALL ( DIM_Contract ) ),
CALCULATE (
SUM ( DIM_Contract[actual_recurring_collection] ),
(
FILTER (
DIM_Contract,
DIM_Contract[DW_ContractID]
= CALCULATE (
MAX ( DIM_Contract[DW_ContractID] ),
ALL ( DIM_Contract ),
DIM_Contract[contract_number] = EARLIER ( DIM_Contract[contract_number] ),
DIM_Contract[DW_EffectiveFromDate] < VALUES ( DIM_Date[Date] )
)
)
),
LASTDATE ( DIM_Date[Date] ),
DIM_Contract[ContractStatusTLA] = "NTU"
)
)
)
Using the last piece of code to get the SUM of the amounts doesn't work - I get an error: Error: Calculation error in measure 'DIM_Contract'[PolicyAPI_NTU]: A table of multiple values was supplied where a single value was expected.
I suspect your problem is here
DIM_Contract[DW_EffectiveFromDate] < VALUES ( DIM_Date[Date] )
The DAX doesn't know how to do a comparison if DIM_Date[Date] has multiple values.
Try using a MAX or MIN or LASTDATE or something similar instead of VALUES.

YTD Measure in DAX Studio doesn't show any value for several dates

Trying to calculate YTD for several dates in DAX STUDIO according to https://www.daxpatterns.com/time-patterns/ guide
I've created a measure in my model, which gets the job done when I use Date Dimension and calculates YTD for every date
CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
But when I'm trying to reproduce the same result using DAX Studio, I get correct result only when I filter CALCULATETABLE for a certain date
This code works perfectly:
EVALUATE
CALCULATETABLE(
ADDCOLUMNS (
VALUES ( 'Date'[Date] ),
"YTD", CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
)
,
'Date'[Date] = DATE(2018,5,1)
)
This code is expected to return YTD for every date in rows, but, unfortunately it doesn't. What am I doing wrong?:
EVALUATE
CALCULATETABLE(
ADDCOLUMNS (
VALUES ( 'Date'[Date] ),
"YTD", CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
)
,
'Date'[Date] >= DATE(2018,5,1)
)
The only difference is = vs >=, but I get empty result for all the rows
Nothing is wrong with the way you defined your measure.
However, when testing the measure, you should try to write your DAX query in a way similar to what client tools like Power BI would do:
EVALUATE
SUMMARIZECOLUMNS(
'Date'[Date],
FILTER('Date', 'Date'[Date] >= DATE(2018,5,1)),
"YTD", CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
)
or even better:
DEFINE MEASURE 'Sales'[Sales Amt YTD] = CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
EVALUATE
SUMMARIZECOLUMNS(
'Date'[Date],
FILTER('Date', 'Date'[Date] >= DATE(2018,5,1)),
"YTD", [Sales Amt YTD]
)
The issue with the way you wrote it, using CALCULATETABLE, is that you create an outside filter context on the 'Date'[Date] column that contains all dates starting from 2018-05-01. When evaluating the YTD logic inside the FILTER statement, MAX('Date'[Year]) uses this filter context, so that it returns whatever year is the largest on your entire 'Date' table (for example 2025).
Remember, that the CALCULATE function only applies a context transition (row context to filter context) when evaluating the first argument. The filter arguments are evaluated on the original filter context.
If you want to stick with your syntax, you could write an additional CALCULATE to force the context transition to apply also to the 2nd argument of the inner CALCULATE call:
EVALUATE
CALCULATETABLE(
ADDCOLUMNS (
VALUES ( 'Date'[Date] ),
"YTD",
CALCULATE( // Additional CALCULATE to force context transition on filter arguments
CALCULATE (
[Sales Amt],
FILTER (
ALL ( 'Date' ),
'Date'[Year] = MAX ( 'Date'[Year] )
&& 'Date'[Date] <= MAX ( 'Date'[Date] )
)
)
)
),
'Date'[Date] >= DATE(2018,5,1)
)
This would be the same as referencing the measure directly, as referencing a measure always does an implicit CALCULATE:
EVALUATE
CALCULATETABLE(
ADDCOLUMNS (
VALUES ( 'Date'[Date] ),
"YTD", [Sales Amt YTD]
),
'Date'[Date] >= DATE(2018,5,1)
)

DAX Query on (Day Over Day)

I have the Sales table and a Date table
I wrote the below query to calculate the DOD Sales
Sales Volume := SUM([Sales])
Sales Volume (Prev) := CALCULATE([Sales Volume], PREVIOUSDAY('Date'[Date])
Sales Volume (DOD) = DIVIDE([Sales Volume]-[Sales Volume (Prev)],[Sales Volume (Prev)])
However, these query above will calculate DOD based on continuous day of a month. My concern is I would like to calculate only those Order Date. For example, I would like to compare Sales on 4/12/2016 and 1/12/2016. ((50-20)/20).
How should i amend the query to achieve that?
You have to create a calculated column to get the previous date:
Previous Date =
CALCULATE (
MAX ( [Order Date] ),
FILTER ( ALL ( 'Table' ), [Order Date] < EARLIER ( 'Table'[Order Date] ) )
)
Then just create the measures with the following expressions:
Sales Volume := SUM('Table'[Sales])
Sales Volume Prev :=
CALCULATE (
SUM ( [Sales] ),
FILTER ( ALL ( 'Table' ), 'Table'[Order Date] = MAX ( [Previous Date] ) )
)
Sales Volume (DOD) :=
DIVIDE ( [Sales Volume] - [Sales Volume Prev], [Sales Volume Prev] )
Let me know if this helps.

DAX - Last Value

I have this table
I would like to create measurement get the last traded value for each day. E.g.
How the DAX query should look like?
You have to create two measures. One for the last time in each date and another to get the value for that date and time.
Last Time :=
CALCULATE(MAX([Time]),FILTER('Table',[Date]=MAX([Date])))
Last Traded Value =
CALCULATE (
MAX ( 'Table'[Traded Value] ),
FILTER ( 'Table', [Date] = MAX ( [Date] ) && [Last Time] = [Time] )
)
Then add Date column to rows and Last Time and Last Traded Value measures to Values pane in a pivot table.
Let me know if this helps.
For example:
DEFINE
VAR TableTMP =
ADDCOLUMNS ( 'Table', "DateTime", [Date] + [Time] )
EVALUATE
SUMMARIZE (
NATURALINNERJOIN (
TableTMP,
SUMMARIZE (
GROUPBY ( TableTMP, [Date], "DateTime", MAXX ( CURRENTGROUP (), [DateTime] ) ),
[DateTime]
)
),
[Date],
[Time],
[Traded Value]
)
With the new window functions in DAX, I think this can be simplified to
Last Traded Value =
CALCULATE (
MAX ( 'Table'[Traded Value] ),
INDEX (
1,
ORDERBY ( 'Table'[Time], DESC ),
PARTITIONBY ( 'Table'[Date] )
)
)

DAX Measure - Summing up values between start-end dates in the same table

I have an "Assignments" Table like this:
Date End Date Allocation1111 Alex AA 11/20/2016 12/30/2016 0.52222 Eric BB 10/20/2016 11/30/2016 0.43333 John CC 10/20/2016 12/30/2016 12222 Eric DD 11/20/2016 1/1/2017 0.5
I also have a simple "Date" Table which DOES NOT have a relationship with the Assignments Table like this:
Date Month Month_Text Year Month-Year10/1/2016 10 Oct 2016 Oct-1610/2/2016 10 Oct 2016 Oct-1610/3/2016 10 Oct 2016 Oct-1610/4/2016 10 Oct 2016 Oct-16
Than I have the following DAX measure:
==============================
Sum of Assignments :=CALCULATE ( SUMX ( Assignments_Tbl, Assignments_Tbl[Allocation] ), FILTER ( VALUES ( Date_Tbl ), Date_Tbl[Date] >= MINX ( Assignments_Tbl, Assignments_Tbl[Start Date] ) && Date_Tbl[Date] <= MAXX ( Assignments_Tbl, Assignments_Tbl[End Date] ) )) * CALCULATE ( DISTINCTCOUNT ( Date_Tbl[Month] ), FILTER ( VALUES ( Date_Tbl ), Date_Tbl[Date] >= MINX ( Assignments_Tbl, Assignments_Tbl[Start Date] ) && Date_Tbl[Date] <= MAXX ( Assignments_Tbl, Assignments_Tbl[End Date] ) ) )
==============================
All seems OK when I have the Start Date and End Date as part of my Pivot Table like below:
Sum of Assignments in a pivot table with Start/End Dates
HOWEVER, if I remove the Start Date and End Date from the pivot table, the measure is calculating incorrectly and I can't find why.
For instance, as the pic below, the red circles show 0.9 for a person name "Eric" in in Oct-2016, instead of 0.4.
Sum of Assignments measure calculating incorrectly
I tried many things, but got stuck on this measure. Any idea?
After some deeper investigation, here is the proper measure:
New Measure =
SUMX (
Assignments_Tbl,
CALCULATE (
SUM ( Assignments_Tbl[Allocation] ) * DISTINCTCOUNT ( Date_Tbl[Month-Year] ),
FILTER (
VALUES ( Date_Tbl ),
Date_Tbl[Date] >= EARLIER ( Assignments_Tbl[Start Date], 1 )
&& Date_Tbl[Date] <= EARLIER ( Assignments_Tbl[End Date], 1 )
)
)
)