I have the following values in Table_1:
date sales_amount
04/01/2021 100.00
04/02/2021 300.00
04/05/2021 500.00
I want to compute a running average, so the average is computed as each day passes, so that my final output looks like this:
date sales_amount running_average
04/01/2021 100.00 100.00
04/02/2021 300.00 200.00
04/05/2021 500.00 300.00
The sales person did not work on 04/03 and 04/04, so I want to exclude them from my running average.
Right now, my output looks like this, which is wrong for what I am doing:
date sales_amount running_average
04/01/2021 100.00 100.00
04/02/2021 300.00 200.00
04/05/2021 500.00 180.00
Any suggestions?
Right now, my DAX code looks like this:
test_new =
VAR LastVisibleDate = MAX('Table_1'[Date])
VAR FirstVisibleDate = MIN('Table_1'[Date])
VAR LastDateWithSales =
CALCULATE(
MAX('Table_1'[Date]),
REMOVEFILTERS()
)
VAR Result =
IF (
FirstVisibleDate <= LastDateWithSales,
CALCULATE(
AVERAGE([Sales_Amount]),
Table_1[Date]
)
)
RETURN
Result
I have added a few lines in the last variable:
Table_1[Date] in the last variable basically means FILTER ( ALL ( Table_1[Date] ), TRUE ), and that will return all of the dates so not useful in your scenario as it will give wrong results, instead write Table_1[Date] <= LastVisibleDate
You don't need REMOVEFILTERS when you have Date column coming from the Dates table and the Date table is marked as a Date table because when a date table is marked as a date table the engine automatically adds a REMOVEFILTERS/ALL whenever a filter is applied over the Date column, but that won't happen with Date column of other tables hence you need to write an explicit REMOVEFILTERS in the last variable
test_new =
VAR LastVisibleDate =
MAX ( 'Table_1'[Date] )
VAR FirstVisibleDate =
MIN ( 'Table_1'[Date] )
VAR LastDateWithSales =
CALCULATE (
MAX ( 'Table_1'[Date] ),
REMOVEFILTERS ()
)
VAR Result =
IF (
FirstVisibleDate <= LastDateWithSales,
CALCULATE (
AVERAGE ( [Sales_Amount] ),
Table_1[Date] <= LastVisibleDate,
REMOVEFILTERS ( Table_1 )
)
)
RETURN
Result
As a best practice always use Date column from a Date table.
Related
I have a measure that totals the values for each date in the table. I want to filter this measure so that I can display only the last 28 days present in the table instead of displaying values for all the dates. Following is the code that works for getting totals for full table:
CALCULATE( SUM(Daily_Reports[Confirmed]),
FILTER( ALL(Daily_Reports),
Daily_Reports[Case_Date] = SELECTEDVALUE(Daily_Reports[Case_Date]) ) )
The 'relative date' filter in the Filters pane does not work because it only accepts the last 28 days based on today's date and not the dates in the table. Please suggest a DAX formula that can filter for the last 28 days present in the table.
Try this code
VAR endDay = LastDate(Daily_Reports[Case_Date])
VAR startDay= DATEADD(endDay,-28,DAY)
VAR setOfDates = DATESBETWEEN(Daily_Reports[Case_Date], StartDate, EndDate )
RETURN
CALCULATE(
SUM(Daily_Reports[Confirmed])
,setOfDates
)
You can try this one:
MS =
CALCULATE (
SUM ( Daily_Reports[Confirmed] ),
FILTER (
ALL ( Daily_Reports[Case_Date] ),
Daily_Reports[Case_Date]
>= SELECTEDVALUE ( Daily_Reports[Case_Date] ) - 28
)
)
This is what finally worked for me. I created a measure (not a column), that returns 1 for the last 28 days with an IF clause, leaving it blank if the date is not in the last 28 days as follows:
Last28 =
VAR MaxDate = LASTDATE( ALL(Daily_Reports[Case_Date]) )
VAR MinDate = DATEADD( MaxDate, -28, DAY )
RETURN
IF( SELECTEDVALUE(Daily_Reports[Case_Date]) >= MinDate && SELECTEDVALUE(Daily_Reports[Case_Date]) <= MaxDate, 1 )
Then I incorporated this measure into the Calculate function as follows:
Daily Cases =
CALCULATE( SUM(Daily_Reports[Confirmed]),
FILTER( ALL(Daily_Reports),
Daily_Reports[Case_Date] = SELECTEDVALUE(Daily_Reports[Case_Date]) && NOT(ISBLANK(Daily_Reports[Last28]))
)
)
I've a table like below in Power BI with only the start and end date with the value between this dates.
Start_date
End_date
Value
2020-12-01
2020-12-03
7
2020-12-04
2020-12-17
8
2020-12-18
2020-12-21
6
2020-12-22
2099-12-31
7
How could I show the value of a specific day (e.g. on 2020-12-20 the show value be 6) using a measure?
If your specific day is in DateTable then write for example:
Measure = calculate( max('Table'[Value]), FILTER(ALL('Table'),
'Table'[Start_date]<= SELECTEDVALUE(DateTable[Date])
&& SELECTEDVALUE(DateTable[Date]) <= 'Table'[End_date] )
)
Let's suppose you set the specific day using a slicer DimDate[Date].
Then you can write your measure like this:
Measure =
VAR DateSelected = SELECTEDVALUE ( DimDate[Date] )
RETURN
SUMX (
FILTER (
Table1,
Table1[Start_date] <= DateSelected &&
Table1[End_date] >= DateSelected
),
Table1[Value]
)
I have 2 tables, AvailabilitiesDB and AvailabilityTemplateDB.
The AvailabilitiesDB table looks like like
IsAvailable StartTime FinishTime Employee_ID Week Day Of the Week
1 25-09-2020 16:00:00 25-09-2020 19:00:00 101 39 5
0 27-08-2020 14:00:00 27-08-2020 17:00:00 13 35 4
1 25-11-2020 09:00:00 25-11-2020 18:00:00 66 48 3
The AvailabilityTemplateDB table looks like this:
Day Of The Week StartTime FinishTime Employee_ID
3 18:00:00 21:00:00 101
2 11:00:00 17:00:00 13
6 06:00:00 20:00:00 66
Here is the issue:
I want to calculate the availability of the employees, meaning their minutes available (so from StartTime to FinishTime).
However, the thing is: The employees all have a template (AvailabilityTemplateDB) which is their go-to work schedule, so if there is not any observations in AvailabilitiesDB, it means that they use their template. But if there is an observation for a specific employee in the AvailabilitiesDB, it means that the template has been overwritten for the specific day. The templates are recurrent every week, which is why they don't have specific dates, and just "Day of the Week".
So I want to calculate something along the lines of: calculate DatesBetween (Minutes), where employee id = employee id, and if there is a data in the availabilitiesDB it must use this number, so for the first observation it would be 180 minutes, but if there is not a date in there, it must take the time from the template table. I find this hard because all I have is "Day of the week" in the template table, and I don't know how i would "convert" it to dates.
This was what I have tried (Not near end result) and obviously it's not supposed to count rows, I was just trying in order to come closer to an answer. Date refers to my date table, which holds unique dates for all of the dates from the AvailabiltiesDB table.
Try =
VAR dates =
DATESBETWEEN (
'Date'[Date].[Date],
MIN ( 'Date'[Date].[Date] ),
MAX ( 'Date'[Date].[Date] )
)
VAR Employee_ID = AvailabilitiesDB[Employee_ID]
VAR Weekdays = AvailabilitiesDB[Day Of the Week]
VAR weekdaysAndDateMatch =
VAR COUNTZ =
CALCULATE (
COUNTROWS ( AvailabilitiesDB ),
FILTER (
AvailabilityTemplateDB,
Weekdays = AvailabilityTemplateDB[Day of the week]
&& Employee_ID = AvailabilityTemplateDB[Employee_ID]))
RETURN IF ( COUNTZ = 0, "Yes", "No" )
My desired outcome would be a column in the AvailabilitiesDB table that summed the availability in minutes per week, for every employee_ID.
I hope you can help me further, thank you in advance.
Events with a duration are simplified by implementing a snapshot table.
Another good practice when dealing with time is to split the date part and the time part in two different columns
So I created a small model with dimension Date, Employees and Time
For this example we just need the months from August to November. To match the Day of the week with the sample data I had to subtract 1.
Date =
ADDCOLUMNS (
CALENDAR ( "2020-08-01", "2020-11-30" ),
"WeekDay", WEEKDAY ( [Date] ) - 1
)
The Employees dimension is
Employees =
ADDCOLUMNS (
DISTINCT ( AvailabilitiesTemplateDB[Employee_ID] ),
"Name", FORMAT ( [Employee_ID], "000" )
)
For the time dimension I created a measure as a parameter with the time granularity to be used also for the snapshot table. This can be changed to adapt the model to the requirements.
To keep a low number of lines for this example I used a 1 hour interval
TimeInterval = VALUE( "01:00:00" )
So the Time table becomes
Time =
SELECTCOLUMNS (
GENERATESERIES ( VALUE ( "00:00:00" ), VALUE ( "23:59:59" ), [TimeInterval] ),
"Time", [Value]
)
The snapshot table is a table containing a row per each time interval for which an employee is available. To build this table we can use the set functions UNION and EXCEPT. The snapshot table has just three columns: the Employee_ID, the Date and the Time
This code matches the Date with the weekday using the Date table we build before
AvailabilitiesSnapshot =
VAR TimeGranularity = [TimeInterval]
VAR AvailableFromTemplateDB =
SELECTCOLUMNS(
GENERATE(
AvailabilitiesTemplateDB,
VAR DayOfWeek = AvailabilitiesTemplateDB[Day Of The Week]
VAR TimesTable =
SELECTCOLUMNS(
GENERATESERIES(
AvailabilitiesTemplateDB[StartTime],
AvailabilitiesTemplateDB[FinishTime] - TimeGranularity,
TimeGranularity
),
"Time", [Value]
)
RETURN
GENERATE(
FILTER( ALLNOBLANKROW( 'Date' ), 'Date'[WeekDay] = DayOfWeek ),
TimesTable
)
),
"Employee_ID", [Employee_ID],
"Date", [Date],
"Time", [Time]
)
VAR AvailableFromDB =
SELECTCOLUMNS(
GENERATE(
CALCULATETABLE( AvailabilitiesDB, AvailabilitiesDB[IsAvailable] = 1 ),
VAR TimesTable =
SELECTCOLUMNS(
GENERATESERIES(
AvailabilitiesDB[StartTimeOnly],
AvailabilitiesDB[FinishTimeOnly] - TimeGranularity,
TimeGranularity
),
"Time", [Value]
)
RETURN
TimesTable
),
"Employee_ID", [Employee_ID],
"Date", [Date],
"Time", [Time]
)
VAR UnavailableFromDB =
SELECTCOLUMNS(
GENERATE(
CALCULATETABLE( AvailabilitiesDB, AvailabilitiesDB[IsAvailable] = 0 ),
VAR TimesTable =
SELECTCOLUMNS(
GENERATESERIES(
AvailabilitiesDB[StartTimeOnly],
AvailabilitiesDB[FinishTimeOnly] - TimeGranularity,
TimeGranularity
),
"Time", [Value]
)
RETURN
TimesTable
),
"Employee_ID", [Employee_ID],
"Date", [Date],
"Time", [Time]
)
RETURN
EXCEPT(
DISTINCT( UNION( AvailableFromTemplateDB, AvailableFromDB ) ),
UnavailableFromDB
)
In this code first we add all available intervals, then we remove the intervals that are marked as not available, those with AvailabilitiesDB[IsAvailable] = 0
Then we create the relationships between this new snapshot table and the dimensions, to get the model
with this model, writing a measure to compute the available minutes is straigthforward
AvailableTime = COUNTROWS( AvailabilitiesSnapshot ) * [TimeInterval] * 24 * 60
The TimeInterval parameter can be changed to rise the detail level. Of course this will increase the number of rows of the snapshot table and also depends on the size of the input tables.
I have slicer date in report. I use the following expression in order to calculate the number of days between two selcted dates
Remaining Days =
VAR a =
FIRSTDATE (MyTimeView[CC_DT_DATE])
VAR b =
CALCULATE ( MAX ( MyTimeView[CC_DT_DATE] ); ALLSELECTED (MyTimeView[CC_DT_DATE]) )
RETURN
DATEDIFF ( a;b; DAY )
When I select 01/01/2020 to 31/01/2020, I am expecting to get 31 days but I get 29 days.
How to modify the expression,?
DATESBETWEEN should work.
Something like:
Remaining Days =
CALCULATE(
COUNTROWS(MyTimeView),
DATESBETWEEN(
MyTimeView[CC_DT_DATE],
MIN(MyTimeView[CC_DT_DATE]),
MAX(MyTimeView[CC_DT_DATE])
)
)
I have a Measure which calculates a cumulative total:
CumulativeCount:=
VAR date1 = MAX( DimDate[Date] )
VAR date2 = MAX( FactTable[EndDate] )
RETURN
CALCULATE (
SUM( FactTable[Count] ),
DimDate[Date] <= date1,
DimDate[Date] <= date2,
ALL( DimDate[Date] )
)
And another, actually used in the Pivot Table, which, when it's calculating the Grand Total, is supposed to add up the cumulative totals for each date:
CumulativeCountForPivot:=
IF (
-- If calculating for one group
COUNTROWS( VALUES( FactTable[Group] ) ) = 1,
-- Do core logic
[CumulativeCount],
-- Else add up the results from each group
SUMX(
VALUES( FactTable[Group] ),
[CumulativeCount]
)
)
I don't understand why the Grand Total in the final column is 12, not 6.
The reason is that the grand total is for GroupA and GroupB combined and there is a cumulative count of 12 on that date (6 for each group).
On 06/01/2017 there are no records for GroupA so the [CumulativeCount] measure is returning a blank, even though there are records before that date and the count would be 6. If you added a record for GroupA with a Count of 0 on 06/01/2017, then you would see 6 appear.
If you want a measure that only shows 6 on that date, then try something like this:
CountForPivot =
VAR TempTable = SUMMARIZE(FactTable,
FactTable[Group],
FactTable[EndDate],
"Cumulative",
CALCULATE(SUM(FactTable[Count]),
FILTER(ALLEXCEPT(FactTable, FactTable[Group]),
FactTable[EndDate] <= MAX(FactTable[EndDate])
)
)
)
RETURN SUMX(TempTable, [Cumulative])