Currently, I have calculated the working days between two date by using the following formula.
TAT = CALCULATE(SUM('Days Table'[Is Work Day]),
DATESBETWEEN('Days Table'[Date],'Re-run Data'[DATE_ORDERED],'Re-run
Data'[DATE_COMPLETED]))
The problem is that if a client level has multiple orders that span all the working days in the Days Table, their sum includes all of the days instead of the sum of days between orders. This also skews the averages.
Does anyone have simpler solution to get number of working days between two dates?
Your current solution relies on having the [Is Work Day] column in your calendar table.
This measure returns the number of working days between the Date Ordered and Date Completed - based on working days being Monday - Friday, and excluding dates listed in a 'Holidays' table, without needing any calculated columns:
TAT =
COUNTROWS (
FILTER (
ADDCOLUMNS(
DATESBETWEEN (
'Calendar'[Date],
MIN ( 'Re-run Data'[DATE_ORDERED] ),
MAX ( 'Re-run Data'[DATE_COMPLETED] )
),
"Is Weekday", WEEKDAY ( 'Calendar'[Date], 2) < 6,
"Is Holiday", CONTAINS ( Holidays, Holidays[Holiday Dates], 'Calendar'[Date] )
),
[Is Weekday] = TRUE() && [Is Holiday] = FALSE()
)
)
See https://pwrbi.com/so_54718437/ for worked example (PBIX)
Upon further analysis, the formula I included in my question does exactly what I need it to do.
Related
I need your help.
I have a table (“Table”) like this.
In the table below I have SUM “sales” by the LATEST 2 days with sale (not the latest 2 DATES! i.e. example: if the latest sales update is on a Tuesday, it sums the sale for Monday and Friday (no sale in weekend)) for each products.
in other words:
The calculation is made with the following DAX calculated column:
Sale last 2 days=
VAR ProductDates =
CALCULATETABLE (
VALUES ( Table[Date]),
ALLEXCEPT ( Table, Table[Product_ID])
)
VAR LastTwoDates = TOPN ( 2; ProductDates;[Date] )
RETURN
CALCULATE (
SUM ([Sale]);
ALLEXCEPT ( Table, Table[Product_ID] );
Table[Date] IN LastTwoDates)
Now, I need to take it a step further:
What I want to do is to make a new calculations which SUM the sale for each product for the latest 2 days, but ONLY for the Distributors, where the "Distributor indicator"=1. And the latest 2 sales days in question, are the sales days where there has been sale to these distributors only.
(example: if the latest sales day is a tuesday and there were no sale from these distributors yesterday, the the latest two days will be previous friday and thursday (i.e. the latest 2 days where sales is not null).
I know I can use the calculation, I have already made, but I can’t figure out where to put the logic in, in order to get the right result:
Example:
I know I can use the calculation, I have already made, but I can’t figure out where to put the logic in, in order to get the right result:
Can some of you please help!
Thanks. It is greatly appreciated.
Br,
Jakob
Assuming there is a date dimension table named "Calendar", this worked for me.
=IF(
COUNTROWS(
INTERSECT(
VALUES('Calendar'[Date]),
CALCULATETABLE(VALUES(Table[Date]), ALL(Table))
)
) > 0,
CALCULATE(
SUM(Table[Sale]),
CALCULATETABLE(
TOPN(2, SUMMARIZE(Table, Table[Date]), Table[Date], DESC),
FILTER(ALL(Table), Table[Date] <= MAX('Calendar'[Date]))
),
ALL('Calendar')
)
)
I need to show how many active contracts we have open for each month in the last 6 months. I am trying to figure out a way to display this. Here is my table
Machine Enrollment# StartDate EndDate
A 1 1/2/2016 6/18/2019
B 2 12/15/2012 5/12/2034
C 3 3/25/2019 4/25/2021
D 4 1/7/2000 7/15/2019
A 5 10/1/2019 10/1/2025
I have thousands of rows. I want to be able to show a rolling 6 month visual for how many machines are under contract. So in this small example it would look like this
Apr-19 June-19 Jul-19 Aug-19 Sep-19 Oct-19
4 4 3 2 2 3
Where do I even begin in creating this? In the past, we have just looked at the numbers for the current month and tacked those results onto the end of a static table and deleted the column from over 6 months ago. I have been assigned to automate this report in Power BI. I am guessing I need to create a column/measure that looks at the EndDate and compares it to the filtered Date in the visual (ie: Aug-19) and determines if the contract was open at that time. But I do not know. Any help is much appreciated. Thanks in advance!
I think I found a solution for what you are looking for. You may find a sample pbix file here.
1. Create a calendar table
A calendar table is required to filter/slice the time periods. The calendar table needs to have a unique Date column, and optional columns such as Year, Quarter, and Month, depending on what units of period you need in the analysis.
A calendar table can be most easily created as a DAX calculated table. Here is an example of a minimal calendar table required in this use case.
Calendar =
ADDCOLUMNS(
CALENDAR( MIN( Contracts[StartDate] ), MAX( Contracts[EndDate] ) ),
"Year Month", FORMAT( [Date], "mmm-yy" ),
"Year Month Number", YEAR( [Date] ) * 100 + MONTH( [Date] )
)
2. Create a measure to calculate number of open contracts
Every numbers calculated and shown in reports need to be defined as measures.
Let's think about the number of May-19. The current filter context includes all 31 dates in the Calendar table between 2019-05-01 and 2019-05-31. In this case, how can we think of an open contract? If the contract starts after 2019-05-31, it is not open. If the contract ends before 2019-05-01, it is not open as well. Therefore the open contract meets this condition.
Starts on or before 2019-05-31 and
Ends on or after 2019-05-01
Below is the measure definition to count the number of contracts based on this condition.
# Open Contracts =
VAR MinDate = MIN( 'Calendar'[Date] )
VAR MaxDate = MAX( 'Calendar'[Date] )
RETURN COUNTROWS(
FILTER(
Contracts,
Contracts[StartDate] <= MaxDate
&& Contracts[EndDate] >= MinDate
)
)
3. Add dynamic filter for last 6 months
If I was understanding correctly, the requirement is to show monthly number of last 6 calendar months, excluding this month. I could not find a straightforward way for this. My solution may contain a bit of hacky scent.
Power BI does not have built-in filter support based on calendar months relative to now. We need to build a custom logic to achieve this. I did it by creating a measure that indicates whether current filter context is within the desired period. This measure is a flag that returns 1 if the filter context is a single calendar month which is included in the last 6 calendar months, or returns BLANK otherwise.
__Last6MonthFlag =
VAR YearMonths = CALCULATETABLE(
VALUES( 'Calendar'[Year Month] ),
REMOVEFILTERS( 'Calendar'[Year Month] ),
'Calendar'[Date] > EOMONTH( TODAY(), -7 )
&& 'Calendar'[Date] <= EOMONTH( TODAY(), -1 )
)
RETURN IF(
HASONEVALUE( 'Calendar'[Year Month] )
&& SELECTEDVALUE( 'Calendar'[Year Month] ) IN YearMonths,
1
)
Then I used this measure in the visual filter like this.
You need to do below activities to achieve your requirement.
Define a calendar table holding all the dates for your report. Define a calculated column for Month-Year. Month-Year = FORMAT('CalendarTable'[Date], "MM-YYYY")
You can define a calculated measure, which will return 1 if the end date of the contract is < 6 months from current date (you can use TODAY() function). This function will help in rolling calculation based on current date. Otherwise, this calculated measure will return NULL and SUM them.
You can drag the month-Year calculated column, defined in step no. 1, to the column axis. You can drag the calculated measure, defined in step no.2, to the values section. PowerBI control by default filters out the NULL values. So, when you use the calculated measure defined in step no. 2, you will get values only for the last 6 months. As the calculation is defined based on TODAY(), it will be a running calculation.
So I know this question has been asked a few times, and I've religiously looked over different approaches, however I still don't quite understand why I'm getting an incorrect result.
Case: I have Sales Data from ~2016 -> 2019 (up until the 2/18/2019) I'm have a Measure to show me the YTD, however I'm looking for a measure for Last Years to date(the 18th in this particular circumstance).
Right now, I have this:
Total Sales LYTD =
CALCULATE (
[Total Sales],
SAMEPERIODLASTYEAR (
FILTER (
VALUES ( Sales[Completed Date] ),
Sales[Completed Date] <= MAX ( Sales[Completed Date] )
)
)
)
The logic to me makes sense, but I'm sure I'm missing something, has it appears it's grabbing the ENTIRE total of 2018 when in reality i'm looking for 01/01/2018 -> 2/18/2018
This is going to be dynamically uploaded with new sales data
What am I missing? Thank you so much!
Not sure I understand your table setup so lets look at this scenario and hopefully it helps.
Suppose you have the data in two tables, Sales and Calendar, and there's a 1:* relationship between the calendar and the sales tables. Then I would write the measures like this:
SalesToDateThisYear =
calculate(
Sum(Sales[Sales]);
Calendar[Year] = Year(Today())
)
and
SalesToDateLastYear =
var dateLastYear = Today() - 365
return
calculate(
Sum(Sales[Sales]);
Calendar[Year] = Year(dateLatsYear);
Calendar[Date] < dateLastYear
)
The two filter arguments are combined with a logic AND. So only dates from the first of last year to today's date last year will be included.
If you want to use the SamePeriod-function you can probably write something like this
SPLY =
calculate =
Sum(Sales[Sales]);
SamePeriodLastYear(
Filter(
Values(Calendar[Date]);
Calendar[Date] >= Date(year(today()); 1; 1) && Calendar[Date] < Today()
)
)
)
The SamePeriod-function takes a set of dates (this year) and converts them to dates last year.
Cheers
I have a measure calculated in the context of a selected month defined as:
MyMetric = COUNTROWS ( FILTER ( Entities, [Incident Count] > [Target] ) )
I need to calculate the YTD number while calculating each month separately. This is because a single Entity that exceeds the Target in two months needs to be counted twice, whereas a simple YTD calculation would only include it once. For example, when reporting March, a correct result is achieved with:
[MyMetric YTD] = [MyMetric]
+ CALCULATE ([MyMetric] , DATEADD(DateTable[Date], -1 , MONTH))
+ CALCULATE ([MyMetric] , DATEADD(DateTable[Date], -2 , MONTH))
Obviously, this is not the right way to do it. How can this kind of calculation be written efficiently?
Let's suppose that you have a Month column in your DateTable. If not, then you can create one.
Then you can try something along these lines:
MyMetric YTD
= SUMX(
CALCULATETABLE(
VALUES( DateTable[Month] ),
DATESYTD( DateTable[Date] )
),
[MyMetric]
)
Basically, you get a list of each month in the year so far and then sum your measure value for each one of those months.
I have following scenario which has been simplified a little:
Costs fact table:
date, project_key, costs €
Project dimension:
project_key, name, starting date, ending date
Date dimension:
date, years, months, weeks, etc
I would need to create a measure which would tell project duration of days using starting and ending dates from project dimension. The first challenge is that there isn't transactions for all days in the fact table. Project starting date might be 1st of January but first cost transaction is on fact table like 15th on January. So we still need to calculate the days between starting and ending date if on filter context.
So the second challenge is the filter context. User might want to view only February. So it project starting date is 1.6.2016 and ending date is 1.11.2016 and user wants to view only September it should display only 30 days.
The third challenge is to view days for multiple projects. So if user selects only single day it should view count for all of the projects in progress.
I'm thankful for any help which could lead towards the solution. So don't hesitate to ask more details if needed.
edit: Here is a picture to explain this better:
Update 7.2.2017
Still trying to create a single measure for this solution. Measure which user could use with only dates, projects or as it is. Separate calculated column for ongoing project counts per day would be easy solution but it would only filter by date table.
Update 9.2.2017
Thank you all for your efforts. As an end result I'm confident that calculations not based on fact table are quite tricky. For this specific case I ended up doing new table with CROSS JOIN on dates and project ids to fulfill all requirements. One option also was to add starting and ending dates as own lines to fact table with zero costs. The real solution also have more dimensions we need to take into consideration.
To get the expected result you have to create a calculated column and a measure, the calculated column lets count the number of projects in dates where projects were executed and the measure to count the number of days elapsed from [starting_date] and [ending_date] in each project taking in account filters.
The calculated column have to be created in the dim_date table using this expression:
Count of Projects =
SUMX (
FILTER (
project_dim,
[starting_date] <= EARLIER ( date_dim[date] )
&& [ending_date] >= EARLIER ( date_dim[date] )
),
1
)
The measure should be created in the project_dim table using this expression:
Duration (Days) =
DATEDIFF (
MAX ( MIN ( [starting_date] ), MIN ( date_dim[date] ) ),
MIN ( MAX ( [ending_date] ), MAX ( date_dim[date] ) ),
DAY
)
+ 1
The result you will get is something like this:
And this if you filter the week using an slicer or a filter on dim_date table
Update
Support for SSAS 2014 - DATEDIFF() is available in SSAS 2016.
First of all, it is important you realize you are measuring two different things but you want only one measure visible to your users. In the first Expected result you want to get the number of projects running in each date while in the Expected results 2 and 3 (in the OP) you want the days elapsed in each project taking in account filters on date_dim.
You can create a measure to wrap both measures in one and use HASONEFILTER to determine the context where each measure should run. Before continue with the wrapping measure check the below measure that replaces the measure posted above using DATEDIFF function which doesn't work in your environment.
After creating the previous calculated column that is required to determine the number of projects in each date, create a measure called Duration Measure, this measure won't be used by your users but lets us calculate the final measure.
Duration Measure = SUMX(FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
),1
)
Now the final measure which your users should interact can be written like this:
Duration (Days) =
IF (
HASONEFILTER ( date_dim[date] ),
SUM ( date_dim[Count of Projects] ),
[Duration Measure]
)
This measure will determine the context and will return the right measure for the given context. So you can add the same measure for both tables and it will return the desired result.
Despite this solution is demonstrated in Power BI it works in Power Pivot too.
First I would create 2 relationships:
project_dim[project_key] => costs_fact[project_key]
date_dim[date] => costs_fact[date]
The Costs measure would be just: SUM ( costs_fact[costs] )
The Duration (days) measure needs a CALCULATE to change the filter context on the Date dimension. This is effectively calculating a relationship between project_dim and date_dim on the fly, based on the selected rows from both tables.
Duration (days) =
CALCULATE (
COUNTROWS ( date_dim ),
FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
)
)
I suggest you to separate the measure Duration (days) into different calculated column/measure as they don't actually have the same meaning under different contexts.
First of all, create a one-to-many relationship between dates/costs and projects/costs. (Note the single cross filter direction or the filter context will be wrongly applied during calculation)
For the Expected result 1, I've created a calculated column in the date dimension called Project (days). It counts how many projects are in progress for a given day.
Project (days) =
COUNTROWS(
FILTER(
projects,
dates[date] >= projects[starting_date] &&
dates[date] <= projects[ending_date]
)
)
P.S. If you want to have aggregated results on weekly/monthly basis, you can further create a measure and aggregate Project (days).
For Expected result 2 and 3, the measure Duration (days) is as follows:
Duration (days) =
COUNTROWS(
FILTER(
dates,
dates[date] >= FIRSTDATE(projects[starting_date]) &&
dates[date] <= FIRSTDATE(projects[ending_date])
)
)
The result will be as expected: