I have the below table and calculating the durations between First_change_Date and Create_date using this DAX formula:
Response_time =
VAR Minutes = DATEDIFF('otrs ticket Response'[otrs ticket.create_time], 'otrs ticket Response'[First_Change_time],MINUTE)
var days =INT(Minutes/1440)
var hourNo=INT(MOD(Minutes,1440) / 60)
var minuteNO=MOD(Minutes,60)
RETURN
CONCATENATE( CONCATENATE( CONCATENATE(days,"d "), CONCATENATE(hourNo, "H ")), CONCATENATE(minuteNO, "m "))
I want to exclude the weekends (Friday, Saturday in my case) and non working hours (5:00pm - 9:00am)
Data:
For my client, I have created a logic. First created a WorkingHoursTable.
Then created a calculated column with the following formula, in the table which has the start and end dateTime's.
Working Hours Between Dates =
var startDate = [yourStartDateTime].[Date]
var startTime = [yourStartDateTime] - startDate
var endDate = [yourEndDateTime].[Date]
var endTime = [yourEndDateTime] - endDate
var firstFullDay = startDate + 1
var lastFullDay = endDate - 1
var inBetweenWorkingHours =
IF(
firstFullDay > lastFullDay,
0,
SUMX(CALENDAR(firstFullDay, lastFullDay), LOOKUPVALUE(WorkingHoursTable[WorkingHoursInAllDay], WorkingHoursTable[WeekDay], WEEKDAY([Date], 2)))
)
var firstDayStart = LOOKUPVALUE(WorkingHoursTable[StartTime], WorkingHoursTable[WeekDay], WEEKDAY(startDate, 2))
var firstDayEnd = LOOKUPVALUE(WorkingHoursTable[EndTime], WorkingHoursTable[WeekDay], WEEKDAY(startDate, 2))
var lastDayStart = LOOKUPVALUE(WorkingHoursTable[StartTime], WorkingHoursTable[WeekDay], WEEKDAY(endDate, 2))
var lastDayEnd = LOOKUPVALUE(WorkingHoursTable[EndTime], WorkingHoursTable[WeekDay], WEEKDAY(endDate, 2))
var effectiveStartTime = IF(startTime < firstDayStart, firstDayStart, startTime)
var effectiveEndTime = IF(endTime > lastDayEnd, lastDayEnd, endTime)
return
IF(
startDate = endDate,
24 * IF(effectiveEndTime > effectiveStartTime, effectiveEndTime - effectiveStartTime, 0),
var firstDayWorkingHour =
24 *
IF(
startTime > firstDayEnd,
0,
firstDayEnd - effectiveStartTime
)
var lastDayWorkingHour =
24 *
IF(
endTime < lastDayStart,
0,
effectiveEndTime - lastDayStart
)
return firstDayWorkingHour + lastDayWorkingHour + inBetweenWorkingHours
)
In this formula you just set the first 4 variables correctly. Then it will calculate total working hours. Unit will be in hours.
Edit: As I see from your post that your weekends are Friday and Saturday, you will need to use WEEKDAY functions slightly different. You can send 1 as a second parameter to WEEKDAY function, instead of 2. You will also need to modify the WeekDay column of WorkingHoursTable.
After this one, you can parse it to '9d 20H 52m' with your formula.
I split the date/time in to date and time columns. I then use a date dimension, where one of the columns is "Is Working Day" = TRUE(), based on which day of the week it is (a simple calculated column). In the time dimension, you do the same to identify "Working Hour" = TRUE(), again, a simple calculation.
Once you have the dimensions in place it then becomes very easy to build your calculations to include / exclude.
Related
I want to calculate and show month on month growth rate in power bi, in both visual - Table and scorecard. In Table all the month should have their respective growth rate, except for current month (in some cases, otherwise can consider current month as well). And in scorecard if no month is selected from the slicer, current/previous month's growth rate should be visible. I had no issue before the year change.
Previously I used the following DAX to get the output:
MoM = VAR CurrentMonth = MONTH(TODAY())
VAR CurrentYear = YEAR(TODAY())
VAR LastYear = CurrentYear-1
VAR CurrentMonthPrice = CALCULATE([TotalPrice], FILTER(AllCommodities, AllCommodities[Year]=CurrentYear && MONTH(AllCommodities[Date])= CurrentMonth))
VAR LastYearMonthPrice = CALCULATE([TotalPrice], FILTER(AllCommodities, AllCommodities[Year]=LastYear && MONTH(AllCommodities[Date])= CurrentMonth))
VAR growth = DIVIDE(CurrentMonthPrice,LastYearMonthPrice)-enter image description here1
RETURN
IF(SELECTEDVALUE(AllCommodities[Commodities])="NA", "-", growth)
But due to year change, I'm unable to calculate the M-o-M rate. I tried using the following formula:
New MoM =
DIVIDE(
SUMX(FILTER(ALLSELECTED(trail), MONTH(trail[Date]) = MONTH(SELECTEDVALUE(trail[Date],NOW())) && YEAR(trail[Date]) = YEAR(SELECTEDVALUE(trail[Date],NOW()))), trail[Revenue]),
SUMX(FILTER(ALLSELECTED(trail), MONTH(trail[Date]) = IF(MONTH(SELECTEDVALUE(trail[Date],NOW()))=1,12,MONTH(SELECTEDVALUE(trail[Date],NOW()))-1) && YEAR(trail[Date]) = IF(MONTH(SELECTEDVALUE(trail[Date],NOW()))=1,YEAR(SELECTEDVALUE(trail[Date],NOW()))-1,YEAR(SELECTEDVALUE(trail[Date],NOW())))), trail[Revenue])) - 1
But it is only good for table visual and if a particular month is selected, it gives -100% error. which should not happen and give that particular month's growth rate.
How do I modify my DAX ?
Old DAX :
MoM = VAR CurrentMonth = MONTH(TODAY())
VAR CurrentYear = YEAR(TODAY())
VAR LastYear = CurrentYear-1
VAR CurrentMonthPrice = CALCULATE([TotalPrice], FILTER(AllCommodities, AllCommodities[Year]=CurrentYear && MONTH(AllCommodities[Date])= CurrentMonth))
VAR LastYearMonthPrice = CALCULATE([TotalPrice], FILTER(AllCommodities, AllCommodities[Year]=LastYear && MONTH(AllCommodities[Date])= CurrentMonth))
VAR growth = DIVIDE(CurrentMonthPrice,LastYearMonthPrice)-1
RETURN
IF(SELECTEDVALUE(AllCommodities[Commodities])="NA", "-", growth)
But it doesn't works for year change.
New DAX:
New MoM =
DIVIDE(
SUMX(FILTER(ALLSELECTED(trail), MONTH(trail[Date]) = MONTH(SELECTEDVALUE(trail[Date],NOW())) && YEAR(trail[Date]) = YEAR(SELECTEDVALUE(trail[Date],NOW()))), trail[Revenue]),
SUMX(FILTER(ALLSELECTED(trail), MONTH(trail[Date]) = IF(MONTH(SELECTEDVALUE(trail[Date],NOW()))=1,12,MONTH(SELECTEDVALUE(trail[Date],NOW()))-1) && YEAR(trail[Date]) = IF(MONTH(SELECTEDVALUE(trail[Date],NOW()))=1,YEAR(SELECTEDVALUE(trail[Date],NOW()))-1,YEAR(SELECTEDVALUE(trail[Date],NOW())))), trail[Revenue])) - 1
But it doesn't work with scorecard or if a month is selected from the slicer , it gives -100% error.
[![Output required][1]][1]
[1]: https://i.stack.imgur.com/7FIV3.png
In my sales table I would like to change cumulative values into single values. Here is sample data from my table.
I created a measure that as far as I know should works for this.
sales_single_values = VAR current_sales = SUM('sales'[sales cumulative]) VAR prev_sales SUM('sales'[sales cumulative]) - CALCULATE( current_sales, 'sales'[period] = 'sales'[period] - 1) Return IF(ISBLANK(prev_sales), BLANK(), current_sales - prev_sales)
But unfortunately the final result on the chart is still the same as I used cumulative values, not single ones. Any ideas what should I change in my measure?
Expected values would be:
Period 1: 4
Period 2: 2
Period 3: 7
As a measure, something like:
sales_single_values =
var prev = max('sales'[period]) - 1
var prev_sales = CALCULATE( SUM('sales'[sales cumulative]), 'sales'[period] = prev)
Return
sum(sales[sales cumulative]) - prev_sales
But this seems like more of a modeling transformation, so do it in PQ, or with a calculated column, like
current sales =
var prev = calculate( max('sales'[period]) ) - 1
var prevSales = calculate( sum(sales[sales cumulative]), all(sales), sales[period] = prev)
return
sales[sales cumulative]-prevSales
I'm pretty new here and also with Power BI and DAX. So please excuse rookie mistakes and dirty code and also bad english :P
So, I created a measure with many variables to spit out a number from 1-12 (clock).
To get to this I have to calculate in 3 different times. One current Date, one which goes back 3 quartals from the current and one which goes back 6 quartals (Current, Shortterm, Longterm). This is the setup. So I have to filter my Data first and then calculate with it.
First, I just wanted to set a Date (01.10.2021) which is fix.
But now I wanted to be dynamic. I wanted the user to choose the "current" date. Or mainly I wanted to put it in a line plot and let the visual do the slicing (with Date on the x-axis) to show development in time. But here my problem begins.
The Problem is - I guess - that I wanted Data to filter which are unaffected from extern filter (from the Visual or slicer)
I tried out the ALL() Function for the calculation so that it will not be affected from the extern slicer. The result is 0. I think I donĀ“t really understand the mechanics behind the ALL() Function and its brother and sister functions, what they do and what they don't do. The docs explanation was also not helpful. I know I did't try out many things but I sat here a few hours and really can't figure things out.
Here is a part of the DAX from the old measure which is relevant for the problem:
OLD clock=
VAR _SHORTTERM = 3
VAR _LONGTERM = 6
VAR _CURRENT_DATE = DATE(2020,10,01)
VAR _SHORT_TERM_DATE = PREVIOUSDAY(
FIRSTDATE(
DATESINPERIOD(
'Date'[Date],
_CURRENT_DATE,
-(3*_SHORTTERM),
MONTH)
))
VAR _LONG_TERM_DATE = PREVIOUSDAY(
FIRSTDATE(
DATESINPERIOD(
'Date'[Date],
_CURRENT_DATE,
-(3*_LONGTERM),
MONTH)
))
VAR _CURRENT_AVERAGE = CALCULATE(
AVERAGE(
Facts_Values[Value]),
'Facts_Values'[Quarter] == _CURRENT_DATE
)
VAR _LONGTERM_AVERAGE = CALCULATE(
AVERAGE(
Facts_Values[Value]),
'Facts_Values'[Quarter] == _LONG_TERM_DATE
)
VAR _SHORTTERM_AVERAGE = CALCULATE(
AVERAGE(
Facts_Values[Value]),
'Facts_Values'[Quarter] == _SHORT_TERM_DATE
)
VAR _LONGTERM_AVERAGE_RELATIVE = (_CURRENT_AVERAGE - _LONGTERM_AVERAGE) / (_LONGTERM - 1)
VAR _SHORTTERM_AVERAGE_RELATIVE = (_CURRENT_AVERAGE - _SHORTTERM_AVERAGE) / (_SHORTTERM - 1)
..
..
..
VAR _ALL = ROUNDDOWN((12 * (RDV+YDV+IDV+RLV+YLV+ILV)),0)+ 1 )
Return _ALL
And then my "dynamic" version
New Clock =
VAR _SHORTTERM = 3
VAR _LONGTERM = 6
VAR _CURRENT_DATE = DATE(
(YEAR(
MIN('Date'[Date]))),MONTH(MIN('Date'[Date])),01)
VAR _SHORT_TERM_DATE = PREVIOUSDAY(
FIRSTDATE(
DATESINPERIOD(
'Date'[Date],
_CURRENT_DATE,
-(3*_SHORTTERM),
MONTH)
))
VAR _LONG_TERM_DATE = PREVIOUSDAY(
FIRSTDATE(
DATESINPERIOD(
'Date'[Date],
_CURRENT_DATE,
-(3*_LONGTERM),
MONTH)
))
VAR _CURRENT_AVERAGE = CALCULATE(CALCULATE(
AVERAGEX(ALL(Facts_Values),
Facts_Values[Value])),
'Facts_Values'[Quarter from] == _CURRENT_DATE
)
VAR _LONGTERM_AVERAGE = CALCULATE(CALCULATE(
AVERAGEX(ALL(Facts_Values),
Facts_Values[Value])),
'Facts_Values'[Quarter from] == _LONG_TERM_DATE
)
VAR _SHORTTERM_AVERAGE = CALCULATE(CALCULATE(
AVERAGEX(ALL(Facts_Values),
Facts_Values[Values])),
'Facts_Values'[Quarter from] == _SHORT_TERM_DATE
)
VAR _LONGTERM_AVERAGE_RELATIVE = (_CURRENT_AVERAGE - _LONGTERM_AVERAGE) / (_LONGTERM - 1)
VAR _SHORTTERM_AVERAGE_RELATIVE = (_CURRENT_AVERAGE - _SHORTTERM_AVERAGE) / (_SHORTTERM - 1)
..
..
..
VAR _ALL = ROUNDDOWN((12 * (RDV+YDV+IDV+RLV+YLV+ILV)),0)+ 1 )
Return _ALL
Hope to find some friendly experts to solve my problem.
I need some help with my measure counting correct in total.
This is the MainTable:
With my Measure "CountPass" I count every ID distinct with the action "pass":
CountPass = CALCULATE(DISTINCTCOUNT(Workflow[ID]),Workflow[action]="pass")
Furthermore with my Measure CountPassPreweek I do same with reference on previous Week by using the a date table:
CountPassPreweek =
var currentweek = SELECTEDVALUE(DateTable[WeekNum])
var currentweekday = SELECTEDVALUE(DateTable[WeekNo])
var currentyear = SELECTEDVALUE(DateTable[Year])
var maxweeknum = CALCULATE(MAX(DateTable[WeekNum]),all(DateTable))
Return
SUMX(
if(currentweek = 1,
DateTable[WeekNo] = currentweekday && DateTable[WeekNum] = maxweeknum && DateTable[Year] = currentyear - 1,
DateTable[WeekNo] = currentweekday && DateTable[WeekNum] = currentweek -1 && DateTable[Year] = currentyear)),
[CountPass]
)
This is working so far but not showing the totals, so I have a second measure for doing that:
CountPreweekTotal =
var _table = SUMMARIZE(DateTable,DateTable[Date],"_value",[CountPassPreweek])
return
SUMX(_table,[_value])
And here you see my problem: The measure doesn't count distinct like the "original" counting Measure as you see here
Hope somebody can help me with that.
Thanks a lot!
It's counting 3 since abc is getting counted twice the way your measure is written (since dates are separated in your SUMMARIZE).
Since you appear to have a proper date table, you should be able to use time intelligence functions to write this much more simply as
CountPassPreviousWeek =
CALCULATE ( [CountPass], DATEADD ( DateTable[Date], -7, DAY ) )
This should work for the total too.
I have Client Services table with [Billable Minutes] value.
I need to create [Moving Average for 3 months] measure, where the calculation will
only happen - if there are values in all 3 months in [Billable Minutes] exist !
(See below)
If [Billable Minutes] value is blank in at least one month in my Client Services table, then I want [Moving Avg] will show 0 or blank!
My goal:
Client Services table: Result:
Period [Billable Minutes] Period [Moving Avg]
2018-11 200 2019-01 200
2018-12 300
2019-01 100
To reach my goal, I am using the following DAX expression for [Moving Avg 3 months]:
Moving Avg 3 month =
VAR PeriodToUse = DATESINPERIOD('Calendar FY'[Date], LASTDATE('Calendar FY'[Date]), -3, MONTH)
VAR Result = CALCULATE(DIVIDE([Billable Minutes], COUNTROWS ('Calendar FY')), PeriodToUse)
VAR ZeroValue=IF(Minx('Client Services',[Billable Minutes])=0,0,Result)
Return Result
But, unfortunately, my end result is:
Client Services table: Result:
Period [Billable Minutes] Period [Moving Avg]
2018-11 200 2018-11 67
2018-12 300 2018-12 167
2019-01 100 2019-01 200
So, it takes an existing values in Client Services table and divides them by the number of periods.
For example for 2018-11, 2018-10, 2018-09 - it takes (200+0+0)/3=66.6 (67 rounded)
But I need the Moving Avg would be empty for 2018-11, because there are no values for 2018-10, 2018-09 in the Client Services table (same - for 2018-12, should not calculate)
Please, HELP!
Updated:
Here is the solution for this (thx to the answer below)
In order to check if there zero in the selected period, extra measures should be created:
Billable Minutes
Moving Avg Prev Month = Calculate('Client Services'[Billable Minutes],
PREVIOUSMONTH('Calendar FY'[Date]))
Billable Minutes
Moving Avg 2nd Prev Month = Calculate
('Client Services'[Billable Minutes Prev Month],
PREVIOUSMONTH('Calendar FY'[Date]))
Then, when you check whether there are zero values - you need to check it - not
just for [Billable Minutes], but for [Billable Minutes] within 3 months period =
within
[Billable Minutes]+[Billable Minutes Prev Month]+
[Billable Minutes 2nd Prev Month]
See the updated below (worked perfect):
enter
Billable Minutes 3 Months Avg =
VAR PeriodToUse = DATESINPERIOD('Calendar FY'[Date],
LASTDATE('Calendar FY'[Date]), -3, MONTH)
VAR Result = CALCULATE(DIVIDE([Billable Minutes],
COUNTROWS ('Calendar FY')), PeriodToUse)
VAR NMonthsPeriodBlank =
if([Billable Minutes] = BLANK(),0,1) +
if([Billable Minutes Prev Month] = BLANK(),0,1) +
if([Billable Minutes 2nd Prev Month] = BLANK(),0,1)
RETURN IF(NMonthsPeriodBlank < 3, BLANK(), Result)
Follow these below steps-
Step-1: Convert your Period column to Date considering 1st date of each month as below-
Step-2: Get back to report by clicking Close & Apply and create this below 4 measures-
total = SUM('Client Services'[Billable Minutes])
total prev = CALCULATE([total],PREVIOUSMONTH('Client Services'[Period]))
total second prev = CALCULATE([total prev],PREVIOUSMONTH('Client Services'[Period]))
3 month avergae =
VAR devide_by = if([total] = BLANK(),0,1) + if([total prev] = BLANK(),0,1) + if([total second prev] = BLANK(),0,1)
VAR total_amount = [total] + [total prev] + [total second prev]
RETURN IF(
devide_by < 3,
BLANK(),
total_amount/devide_by
)
Here is the final output-
====================
Solution in single measure
====================
You can convert all measures into 1 measure as below-
3 month average new =
VAR this_month = SUM('Client Services'[Billable Minutes])
VAR prev_month =
CALCULATE(
SUM('Client Services'[Billable Minutes]),
PREVIOUSMONTH('Client Services'[Period])
)
VAR second_prev_month =
CALCULATE(
SUM('Client Services'[Billable Minutes]),
PREVIOUSMONTH(
DATEADD(
'Client Services'[Period],
-1,
MONTH
)
)
)
VAR devide_by =
if(this_month = BLANK(),0,1) +
if(prev_month = BLANK(),0,1) +
if(second_prev_month = BLANK(),0,1)
VAR total_amount = this_month + prev_month + second_prev_month
RETURN IF(
devide_by < 3,
BLANK(),
total_amount/devide_by
)