I am working on a problem involving the scope of DAX variables. My code defines the hire date and termination date of employees and them implements logic based on the result. My problem is that the scope of my variable is NOT in the row context of each employee, rather, its shows the minimum hiredate and maximum hiredate for ALL employees.
Employment Cases =
VAR PeriodStart =
DATE ( 2022, 01, 01 )
VAR PeriodEnd =
DATE ( 2022, 03, 31 )
VAR Hire =
MIN ( attr_Tkpr_vw[TkprDateHire] ) // How do I define this variable so that it results in each employees hire date?
VAR Term =
MIN ( attr_Tkpr_vw[TkprDateTerm] ) // How do I define this variable so that it results in each employees term date?
VAR ReportPeriod =
DATEDIFF ( PeriodStart, PeriodEnd, MONTH )
VAR S3 =
DATEDIFF ( Hire, PeriodEnd, MONTH ) / ReportPeriod
VAR S4 =
DATEDIFF ( Hire, Term, MONTH )
RETURN
SELECTCOLUMNS (
attr_Tkpr_vw,
"EmpID", attr_Tkpr_vw[TkprNumber],
"Hire", attr_Tkpr_vw[TkprDateHire],
"Term", attr_Tkpr_vw[TkprDateTerm],
"Hire Test", Hire,
"Term Test", Term,
"Employment Period",
SWITCH (
TRUE (),
AND (
AND (
attr_Tkpr_vw[TkprDateHire] >= PeriodStart,
attr_Tkpr_vw[TkprDateHire] <= PeriodEnd
),
attr_Tkpr_vw[TkprDateTerm] >= PeriodEnd
), S3,
AND (
AND (
attr_Tkpr_vw[TkprDateHire] >= PeriodStart,
attr_Tkpr_vw[TkprDateHire] <= PeriodEnd
),
AND (
attr_Tkpr_vw[TkprDateTerm] >= PeriodStart,
attr_Tkpr_vw[TkprDateTerm] <= PeriodEnd
)
), S4
)
)
I suspect an iterator function is missing. I tried enclosing the SELECTCOLUMNS expression with CALCULATETABLE. This did not work.
The result set shows that in each case the Hire and Term dates are calculated for the entire table, not each individual.
enter image description here
You need to move the variable scope to inside the SELECTCOLUMNS:
SELECTCOLUMNS (
attr_Tkpr_vw,
"EmpID", attr_Tkpr_vw[TkprNumber],
"Hire", attr_Tkpr_vw[TkprDateHire],
"Term", attr_Tkpr_vw[TkprDateTerm],
"Hire Test", VAR Hire = attr_Tkpr_vw[TkprDateHire]
RETURN Hire,
If you want to do MIN functions then I believe you need a CALCULATE statement to transition the row context to a filter context:
SELECTCOLUMNS (
attr_Tkpr_vw,
"EmpID", attr_Tkpr_vw[TkprNumber],
"Hire", attr_Tkpr_vw[TkprDateHire],
"Term", attr_Tkpr_vw[TkprDateTerm],
"Hire Test", VAR Hire = CALCULATE(MIN(attr_Tkpr_vw[TkprDateHire]))
RETURN Hire,
Related
I have a table FactSales
And tried but didn’t get ant satisfactory result.
Id like to calculate old results and compare to my actual one and see how many customers whose bought product B before (before 90 days) didn’t buy the same product in last 3 months according to the date filter
I tried this:
Customers inactive =
VAR Daysbefore90: Max(DimDate[date]) -90
> RETURN CALCULATE( DISTINCTCOUNT(FSales[CustomerKey]); DimProduct[Product] = “A”; FILTER( ALL ( DimDate[Date] );
DimDate[Date] < DaysBefore90 ); NOT(CONTAINS( FILTER(FSales;
RELATED(DimDate[Date]) >= Daysbefore90 && DimDate[Date]) <=
MAX(Daysbefore90): RELATED(DimProduct[Product]) = “A”) ;
FSales[CustomerKey]; FSales[CustomerKey] ) ) )
This will get you all customer who purchased item 'B' in the last 90 Days:
Customers Who Bought Product B 90 Days Ago :=
CALCULATE (
DISTINCTCOUNT ( 'FSale'[CustomerKey] ),
ALL ( 'DimDate'[Date] ),
KEEPFILTERS (
DATESINPERIOD ( 'DimDate'[Date], MAX ( 'DimDate'[Date] ), -90, DAY )
),
KEEPFILTERS ( DimProduct[Product] = "B" )
)
Your question is a little hard to read, so maybe update it and we can go from there.
I have an issue that I need a hand with. I am using a disconnected slicer based off of this table
Time Frame :=
DATATABLE("ID", Integer, "Time Frame", string
, {
{1, "3 Month"}
, {2, "6 Month"}
, {3, "9 Month"}
, {4, "12 Month"}
})
that looks like this:
Using a few DAX measures:
Sum Of Paid := sum(Data[Paid])
Sum Of Paid 3 Month Period :=
CALCULATE (
[Sum Of Paid],
DATESINPERIOD ( Data[Date], LASTDATE ( Data[Date] ), -3, MONTH )
)
Sum Of Paid 6 Month Period :=
CALCULATE (
[Sum Of Paid],
DATESINPERIOD ( Data[Date], LASTDATE ( Data[Date] ), -6, MONTH )
)
Sum Of Paid 9 Month Period :=
CALCULATE (
[Sum Of Paid],
DATESINPERIOD ( Data[Date], LASTDATE ( Data[Date] ), -9, MONTH )
)
Sum Of Paid 12 Month Period :=
CALCULATE (
[Sum Of Paid],
DATESINPERIOD ( Data[Date], LASTDATE ( Data[Date] ), -12, MONTH )
)
Slicer - Paid Per Period :=
VAR selection =
IF (
HASONEVALUE ( 'Time Frame'[Time Frame] ),
VALUES ( 'Time Frame'[Time Frame] ),
"All"
)
VAR ThreeMonth = [Sum of Paid 3 Month Period]
VAR SixMonth = [Sum of Paid 6 Month Period]
VAR NineMonth = [Sum of Paid 9 Month Period]
VAR TwelveMonth = [Sum of Paid 12 Month Period]
RETURN
SWITCH (
TRUE (),
selection = "3 Month", ThreeMonth,
selection = "6 Month", SixMonth,
selection = "9 Month", NineMonth,
selection = "12 Month", TwelveMonth,
TwelveMonth
)
I can simulate a slicer and display 3, 6, 9 and 12 month aggregates depending on the users selection. These work just fine in cards, choropleths and almost everything I've needed them for. My issue is trying to create line graphs, bar charts, etc that have a date range on the x-axis. I can't for the life of me figure out how to replicate the period referenced in the DAX measure to dynamically set the x-axis.
I've tried a few approaches that seem like they should work but do not:
3 Month Period :=
CALCULATE (
VALUES(Data[Date]),
DATESINPERIOD ( Data[Date], LASTDATE ( Data[Date] ), -3, MONTH )
)
Any help is appreciated.
Thanks
You might want to try this one:
3 Month Period :=
CALCULATE (
[Sum Of Paid],
KEEPFILTERS (
DATESINPERIOD (
Data[Date],
CALCULATE (
MAX ( Data[Date] ),
ALLSELECTED ()
),
-3,
MONTH
)
)
)
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)
)
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] )
)
)
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]
)