Custom Calendar for sales data aggregated by weeks and months - powerbi

I am struggling with creating Custom Calendar that would allow me to use time intelligence function on data that is already aggregated by weeks and months. The original table with transactions contains over 20M rows, so for performance and space saving reasons the grouping is necessary and I perform it while querying the database in SQL Server. I want to create:
Month vs Same Month Last Year
Week vs Same Week Last Year
Year-To-Date vs Last Year Year-To-Date (by Months)
Year-To-Date vs Last Year Year-To-Date (by Weeks)
My idea was to assign some dummy dates to each row of data, and then create custom calendar that would have each of these dummy dates along with other details. I just cannot figure out the key (how to create dummy date having Year number Month number and Week number - please keep in mind that for example Week 5 of 2020 is partially in January and partially in February)
Is it possible? Maybe I have to create 2 separate Calendars, one for Weeks and one for Months?

Add calculated table:
Calendar =
GENERATE (
CALENDAR (
DATE ( 2016, 1, 1 ),
DATE ( 2020, 12, 31 )
),
VAR VarDates = [Date]
VAR VarDay = DAY ( VarDates )
VAR VarMonth = MONTH ( VarDates )
VAR VarYear = YEAR ( VarDates )
VAR YM_text = FORMAT ( [Date], "yyyy-MM" )
VAR Y_week = YEAR ( VarDates ) & "." & WEEKNUM(VarDates)
RETURN
ROW (
"day" , VarDay,
"month" , VarMonth,
"year" , VarYear,
"YM_text" , YM_text,
"Y_week" , Y_week
)
)
You can customize it. In relation pane connect your Date field of FactTable (which is by week, as you say. This table can have missing dates and duplicate dates, to be precise) to the field Date of the Calendar table (which has unique Date, by day). Then, in all your visuals or measures always use the the Date field of the Calendar table. It is a good practice to hide the field Date in your FactTable.
More explanations here https://stackoverflow.com/a/54980662/1903793

Related

How to create Last 12 months flag for grouped data in power bi

I have a table where where I want to create last 12 months flag column from the latest date available in each country. I have tried many Dax formula without success.
My table looks like below:
Here Y indicates the dates falls under last twelve months.
Please help me to find this flag.
You can create a calculated column to validate the date falls within the last 12 months, for each country. First calculate the maxDate for each country, then ensure the date is greater than the MaxDate with an if statement
Last 12 Months =
VAR MaxDate = CALCULATE (
MAX ( Country[Date] ),
ALLEXCEPT ( 'Country', 'Country'[Country] )
)
RETURN
IF (
Country[Date]> DATE(YEAR(MaxDate)-1, Month(MaxDate), Day(MaxDate)) ,1,0
)
This will then give you a filterable column to work from

Power Bi DAX: Relative Date Filtering

I have a quick question, is there a way to filter data from set days between 2 months?
E.g filter from 16-15 of Jan-Feb.
Is this possible?
For example i have used a measure to calculate days between dates
Last Assessment 16-15
= CALCULATE(SUM('Table1'[Duration1]),'Table1'[Start],
DATESBETWEEN('Calendar'[Date], [Assessment Date], [Assessment one month]))
Assessment Date = if(DAY(TODAY())<16,DATE(YEAR(TODAY()),MONTH(TODAY())-1,15),
DATE(YEAR(TODAY()),MONTH(TODAY()),15))
Assessment one month = EDATE([Assessment Date],-1)+1
Assessment 6 = EDATE([Assessment Date],-6)+1
Assessment 12 = EDATE([Assessment Date],-12)+1
The last assessment does show from the 16th of 2 months ago to last months 15th e.g Dec 16th - Jan 15th.
But i need to show from last 6 months and the last 1 year.
How can i work this out so i can show the Last 6 months and 1 year.
So far i have had to use a date filter to manually select the dates which i want to stop and have it be automatic.
If it is just the last 6 months or the last year you could make a custom column in the query editor (this would be the easiest way then). Like a filter flag:
'Includes the current month
Last 6 Months Flag = Date.IsInPreviousNMonths([YourDate], 6) or Date.IsInCurrentMonth([YourDate])
'Without the current month
Last 6 Months Flag = Date.IsInPreviousNMonths([YourDate], 6)
The same for last year:
Last Year Flag = Date.IsInPreviousYear([YourDate])
Drag and drop these custom columns as filter on your report and you are done.
consider following measure for Latest assessment (basically what you had before with EDATE for safe Dec/Jan handling and with variables for better performance)
Latest Assessment Date =
VAR __today = TODAY()
RETURN
IF (
DAY ( __today ) < 16,
DATE ( YEAR ( __today ), MONTH(EDATE(__today, - 1)), 15 ),
DATE ( YEAR ( __today ), MONTH ( __today ), 15 )
)
then you have this measure for handling 1/6/12 scenarios, you just replace 12 with whatever number of months you need
Measure 12 =
VAR __nrOfMonthsBack = 12
VAR __lastAssesment = [Latest Assessment Date]
RETURN
CALCULATE (
SUM ( Table1[Duration] ),
ALL('Calendar'), --this will reset any date filters coming from slicers
DATESBETWEEN (
'Calendar'[Date],
EDATE ( __lastAssesment, - __nrOfMonthsBack ) + 1,
__lastAssesment
)
)
EDIT: added ALL('Calendar') to disable filters coming from slicers

Rolling 6 month Open Contracts in Power BI

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.

Displaying a text value in a card that changes depending on today's date in PowerBi

I have a date table which has "Date" and the column I'm interested in which is "AcaWeekOfTerm". It also has a "CurWeekOffset" column which is populated with 0 for each date in the current week.
I want a Card visual which shows the AcaWeekOfTerm for today's date, and I want it to change each week.
The pseudocode for what I'm after would be CurrentAcademicWeek=TextValue of AcademicWeekofTerm where Calendar[WeekOffset]=0
I can get a card which shows today's Month using Month(Today()) but that's the closest I've been able to get since.
Note this card should also remain the same regardless of what filters are applied to the report\visualisations.
Any advice would be great
Example data
Create a measure which returns the first nonblank value of the text column you want, with appropriate date filters applied.
If you already have the CurWeekOffset field available, then you can use:
Current Academic Week =
CALCULATE (
FIRSTNONBLANK ( DateTable[AcaWeekofYear], 1),
FILTER (
ALL ( DateTable ),
DateTable[CurWeekOffset] = 0
)
)
Or you can filter by today's date:
Current Academic Week (By Date) =
CALCULATE (
FIRSTNONBLANK ( DateTable[AcaWeekofYear], 1),
FILTER (
ALL ( DateTable ),
DateTable[Date] = TODAY()
)
)
Worked example PBIX file: https://pwrbi.com/so_58655282/

Slicer managing multiple columns across tables simultaneously

I have a report page which contains tables about cars and bikes. Each of them is a separate table like:
Cars
Id | CarName | Time1
Bikes
Id | BikeName | Time2
There are no relationships between these tables however they must be displayed in same page. How can i use a Slicer or a Timeline 2.0.1 to manipulate all dashboards simultaneously by just filtering once the date?
I.e. If i select interval between 01/01/19-02/02/19 it will filter the Cars by field Time1 and the Bikes by Time2 and display the dashboards accordingly?
Thanks so much!
Build a CalendarTable and link both tables bikes and cars to it. You may find lots of propositions of CalendarTables. Then make slicer on CalendarTable. Beware not to make slicer on your fact tables bikes or cars.
There are more advantages to using CalendarTable then just the possibility of filtering multiple tables. I would use CalendarTable even with a single table because it contains complete list of days - your bike table may not - and that is why time intelligence functions work properly. And mind the performance - slicing small and unique CalendarTable is faster then big fact tables.
Here is an example of simple CalendarTable. Choose in menu Modeling / New Table:
Calendar =
GENERATE (
CALENDAR (
DATE ( 2016, 1, 1 ),
DATE ( 2020, 12, 31 )
),
VAR CurrentDay = [Date]
VAR day = DAY ( CurrentDay )
VAR month = MONTH ( CurrentDay )
VAR year = YEAR ( CurrentDay )
VAR YM_text = FORMAT ( [Date], "yyyy-MM" )
RETURN
ROW (
"day" , day,
"month" , month,
"year" , year,
"YM_text" , YM_text
)
)
Set up min and max date. Here from 2016-01-01 to 2020-12-31.