I have the following which seems to function ok but looks like I might have done my usual trick of not keeping as simple as possible - what is the elegant version of this measure?
Num Users for Current Month =
VAR
MaxMonth = MONTH(LASTDATE(ALL('Date'[Day Marker])))
VAR
MaxYear = YEAR(LASTDATE(ALL('Date'[Day Marker])))
RETURN
CALCULATE(
[Num Users]
,FILTER(
'Date',
MONTH('Date'[Day Marker]) = MaxMonth
&&
YEAR('Date'[Day Marker]) = MaxYear
) )
With this code you are not selecting the current month. You are selecting the last available month in your selection of dates.
I would rather expand my date table with an extra field: IsCurrentMonth:
IsCurrentMonth =
IF (
YEAR ( Date[Date] ) = YEAR ( TODAY () )
&& MONTH ( Date[Date] ) = MONTH ( TODAY () ),
"Yes",
"No"
)
Then you measure can be rewritten towards:
CALCULATE([Num Users], Date[IsCurrentMonth]="yes")
Related
Please help to calculate/understand properly lastDate and rankDate measures for following simplified example (download):
Desired result:
Reality (incorrect subtypes):
Why relationship is broken?
How to avoid this cartesian product lines?
My Measure (I commented workaround, because it's kind of postfilter, not prefilter):
rnkDate =
VAR t =
CALCULATETABLE(
VALUES(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
RETURN
//IF( MAX(tstTable[Amount])<>BLANK(), // WORKAROUND To hide unwantedd rows
RANKX(
t,
LASTDATE(tstTable[Date])
)
//)
P.S. Mess happens only if I use fields from dimensional table dimType[Type] (within one table everything is Ok):
The problem is that the query generated by Power BI performs the cartesian product and filers the result by checking the result of the measure.
in our case is something similar to
SUMMARIZECOLUMNS(
'dimType'[Type],
'tstTable'[subType],
'tstTable'[Date],
"MinAmount", CALCULATE(MIN('tstTable'[Amount])),
"lastDate", 'tstTable'[lastDate],
"rnkDate", 'tstTable'[rnkDate]
)
SUMMARIZECOLUMNS doesn't use relationships when iterating on different tables, it applies them when evaluating the measures. There is an article explaining what is the equivalent DAX code executed by SUMMARIZECOLUMNS
Introducing SUMMARIZECOLUMNS
the problem is that RANKX evaluated on an empty table retuns 1. This can be seen executing this on dax.do
EVALUATE
VAR t =
FILTER ( ALL ( 'Date'[Date] ), FALSE )
RETURN
{ RANKX ( t, [Sales Amount] ), CALCULATE ( [Sales Amount], t ) }
so the solution is to first check that the table t is not empty, which is the reason because the workaround that you implemented solved the issue
lastDate =
IF( NOT ISEMPTY(tstTable), // checks fact table in particular context
CALCULATE(
LASTDATE(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
)
rnkDate =
VAR t =
CALCULATETABLE(
VALUES(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
RETURN
IF( NOT ISEMPTY(tstTable),
RANKX(
t,
LASTDATE(tstTable[Date])
)
)
I am trying to calculate the variance of projects, over different periods.
Periods are referenced as P1, P2,...
The user should be able to pick the periods that they want to compare and see the projects listed
new table
I have tried a dax formula, but I can't find one that has more than one filter.
My DAX:
Variance =
VAR DIFF =
WIP[WIP]
- CALCULATE (
SUM ( WIP[WIP] ),
FILTER ( 'WIP', WIP[Index1] = EARLIER ( WIP[Index] ) )
)
RETURN
IF ( DIFF = VALUE ( WIP[WIP] ), 0, DIFF )
Can you help?
2nd table
Variance =
VAR currentPeriod = SELECTEDVALUE('tbl'[Period])
VAR currentObj = SELECTEDVALUE(tbl[Object])
VAR firstPeriodInSelection=
CALCULATE(
MIN('tbl'[Period])
,'tbl'[Object]=currentObj
,ALLSELECTED('tbl'[Period])
,ALLEXCEPT(tbl,tbl[Period],tbl[Object])
)
VAR prevPeriod =
CALCULATE(
MAX('tbl'[Period])
,'tbl'[Period]<currentPeriod
,'tbl'[Object]=currentObj
,ALL()
)
VAR currentWIP =
CALCULATE(
AVERAGE(tbl[WIP])
,ALLEXCEPT(tbl,tbl[Object],tbl[Period])
)
VAR prevWIP =
CALCULATE(
AVERAGE(tbl[WIP])
,ALLEXCEPT(tbl,tbl[Object])
,'tbl'[Period]=IF(
prevPeriod < firstPeriodInSelection
,firstPeriodInSelection
,prevPeriod
)
)
RETURN
currentWIP-prevWIP
Please, pay attention that on my picture you can see 2 values for one period-object. For this case I used average. So, if it will be one value for period-object then you see the value, if it will be several then you will see calculated Variance for average.
We have a report connected, via a live connection, to an analysis services tabular model.
We have this measure:
MeasureX=
VAR NumLogins =
CALCULATE (
[Measure Dynamic Agg],
'Time Periods'[PeriodCalc] = "Current MtD",
'Calendar'[Is Current Month] = "TRUE",
'Measures - Financial Agg'[Formula] = "Num Logins",
ALL ( 'Measures - Financial'[Formula] )
)
VAR NumCategories =
CALCULATE (
[Measure Dynamic],
'Time Periods'[PeriodCalc] = "Current MtD",
'Calendar'[Is Current Month] = "TRUE",
'Measures - Financial'[Formula] = "Num Categories",
ALL ( 'Measures - Financial Agg'[Formula] )
)
RETURN
DIVIDE(NumLogins ,NumCategories)
In the dashboard this returns blanks everywhere.
If we change the last line of DAX to the following it returns numbers as expected:
...
...
RETURN
NumLogins / NumCategories
Does anyone have any clue what is happening? I was under the impression that semantically using the / operator and DIVIDE function were the same, apart from handling divide by zero differently?
DIVIDE handles both zeroes and blanks in the denominator. It's the blanks that are getting you here. Check out https://learn.microsoft.com/en-us/dax/best-practices/dax-divide-function-operator.
Table 1 (Combined Hours) I have a list of [payweek], which is many repeated
Table 2 (All Scripts), I have a list of jobs and two dates, [Scripting Date] and [R4PreScriptDate]
I am trying to find the number of unique [payweek]s between the [Scripting Date] and the [R4PreScriptDate]
The DAX formula is below. My result is always 3. However, I am expecting variable answers (0,1, 2,3,4 or 5)
R4PreScriptWkCt = CALCULATE(DISTINCTCOUNTNOBLANK(CombinedHours[payWeek]),FILTER(CombinedHours,
CombinedHours[payWeek] <= MAX (AllScripts[Scripting Date] )
&& CombinedHours[payWeek] >= MAX (AllScripts[R4PreScriptDate] ) ))
Thank you,
I assumed that both tables are related by Job Number. I created the following measure:
R4PreScriptWkCt =
VAR __date2 = MAX ( AllScripts[R4PreScriptDate] )
VAR __date1 = MAX ( AllScripts[Scripting Date] )
VAR __job = MAX ( AllScripts[Job Number] )
VAR __subTable =
FILTER (
CombinedHours,
CombinedHours[Job Number] = __job
&& CombinedHours[Week] >= __date1
&& CombinedHours[Week] <= __date2
)
RETURN
CALCULATE ( DISTINCTCOUNTNOBLANK ( CombinedHours[Week] ), __subTable )
Hope it helps you.
I need to find the next three available business days for a scheduling application. What is available depends upon excluded dates in a table. So...as long as the date is not in my table and not a Saturday or Sunday, I want the next three. I'd like to find an efficient way of doing this.
I need to return a List<DateTime>. The table is simple - ExcludedDates has an ID and a DateTime with the excluded date.
I'd like to have a single LINQ query expression but can't figure it out...thanks to all in advance and I apologize if this is trivial or obvious - it isn't to me.
Try this...
DateTime start = DateTime.Now.Date;
var result = Enumerable.Range(1, 10) // make this '10' higher if necessary (I assume you only exclude non-workingdays like Christmas and Easter)
.Select(offset => start.AddDays(offset))
.Where(date => !( date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek== DayOfWeek.Sunday))
.Where(d=> !exceptionTable.Any(date => date == d))
.Take(3).ToList();
List<DateTime> result = (from i in Enumerable.Range(1, excludeTable.Rows.Count + 6)
let date = inputDate.AddDays(i)
where date.DayOfWeek != DayOfWeek.Saturday &&
date.DayOfWeek != DayOfWeek.Sunday &&
!excludeTable.Rows.Cast<DataRow>().Select(r => (DateTime) r["ExcludeDate"]).Contains(date)
select date).Take(3).ToList();
excludeTable.Rows.Count + 6 is to cover the worst case where you skip over every thing in the excludeTable and then you have to skip over another weekend.
This assumes that a month will be reasonable depending on your excluded dates.
DateTime date = DateTime.Today;
// first generate all dates in the month of 'date'
var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n));
// then filter the only the start of weeks
var results = (from d in dates
where d.DayOfWeek != DayOfWeek.Saturday && d.DayOfWeek != DayOfWeek.Saturday && !excludes.Any(i => i.DateTime.Date == d.Date) && date < d
select d).Take(3);
var excludedList = new List<long>() { DateTime.Parse("2011-07-27").Ticks };
var week = new List<long>(){
DateTime.Now.Date.Ticks,
DateTime.Now.Date.AddDays(1).Ticks,
DateTime.Now.Date.AddDays(2).Ticks,
DateTime.Now.Date.AddDays(3).Ticks,
DateTime.Now.Date.AddDays(4).Ticks,
DateTime.Now.Date.AddDays(5).Ticks,
DateTime.Now.Date.AddDays(6).Ticks,
DateTime.Now.Date.AddDays(7).Ticks,
DateTime.Now.Date.AddDays(8).Ticks
};
var available = (from d in week.Except(excludedList)
where new DateTime(d).DayOfWeek != DayOfWeek.Saturday && new DateTime(d).DayOfWeek != DayOfWeek.Sunday
select new DateTime(d)).Take(3);
foreach (var a in available)
Console.WriteLine(a.ToString());