How to break down date range by each month in DAX Power BI? - powerbi

I have two dates:
'2018-01-05' and '2019-01-05'
How to create calculated table to break down those dates by month.
Should look simething like that:

There are probably many ways to do this, but here's one way that combines a few different concepts:
Table =
VAR Starting = DATE(2018, 1, 5)
VAR Ending = DATE(2019, 1, 5)
VAR MonthTable =
SUMMARIZE(
ADDCOLUMNS(
CALENDAR(Starting, Ending),
"StartDate", EOMONTH([Date], 0) + 1),
[StartDate],
"EndDate", EOMONTH([StartDate], 0) + 1)
RETURN UNION(
ROW("StartDate", Starting, "EndDate", EOMONTH(Starting, 0) + 1),
FILTER(MonthTable, [EndDate] < Ending && [StartDate] > Starting),
ROW("StartDate", EOMONTH(Ending, -1) + 1, "EndDate", Ending)
)
Basically, you start with the CALENDAR function to get all the days, tag each date with its corresponding month, and then summarize that table to just return one row for each month.
Since the first and last rows are a bit irregular, I prepended and appending those to a filtered version of the summarized month table to get your desired table.

Create new table as
Table = CALENDAR( DATE(2018, 5, 1), DATE(2019, 1, 5) - 1)
Rename auto-generated column "Date" into "Start Date". Add new column as
End Date = Start Date + 1

Related

Need formula to apply in power bi report

I need to add one calculated column in power bi dax. In my excel data there is month end column as shown in table.
As you can see, W05 is last week of 01/2020 (Report Month), so month end is Y, for rest it is N. Same way, W09 is last week of 02/2020 (Report month), month end= Y. rest is N. Can you help me with the formula I can use in power bi to poplulate end month (N or Y)?
Create this following measure-
is_last_week =
var current_report_week = MIN(your_table_name[report week])
var current_minth_max_report_week =
CALCULATE(
MAX(your_table_name[report week]),
ALLEXCEPT(your_table_name,your_table_name[report month])
)
RETURN
IF(
current_minth_max_report_week = current_report_week,
"Y",
"N"
)
For Custom Column, use this below code-
is_last_week =
var current_report_week = your_table_name[report week]
var current_month_max_report_week =
CALCULATE(
MAX(your_table_name[report week]),
ALLEXCEPT(your_table_name,your_table_name[report month])
)
RETURN
IF(
current_month_max_report_week = current_report_week,
"Y",
"N"
)
Here is the final output-

Sum row with next row value and grab next value in other column for the date selected

Let's say I have this data:
Earn Earn Cum.
13-Apr - -
14-Apr 48 48
15-Apr 257 305
16-Apr 518 823
17-Apr 489 1,312
18-Apr 837 2,149
19-Apr 1,005 3,154
20-Apr 1,021 4,175
21-Apr 1,463 5,638
22-Apr 2,630 8,268
23-Apr 2,993 11,261
24-Apr 3,354 14,615
25-Apr 4,332 18,947
26-Apr 4,885 23,832
27-Apr 4,514 28,346
28-Apr 4,356 32,702
29-Apr 4,824 37,526
30-Apr 7,082 44,608
1-May 6,091 50,699
2-May 1,407 52,106
When a date is selected in a dropdown slicer for example: 1-May I'd like to sum the rows 1-May with the next row 2-May for the column Earn and grab the next value 52,106 for the column Earn Cum.. The result should be:
1-May 7,498 52,106
Another example: if the date selected was 30-Apr the result must be:
30-Apr 13,173 50,699
I'm scratching my head trying to do this using a measure in Power BI.
I'll call your table "Data".
Create a measure:
Next Earn =
VAR Current_Date = MAX ( Data[Date] )
VAR Next_Date = Current_Date + 1
RETURN
CALCULATE (
SUM ( Data[Earn] ),
Data[Date] = Current_Date || Data[Date] = Next_Date
)
Create another measure:
Next Cum Earn =
VAR Current_Date = MAX ( Data[Date] )
VAR Next_Date = Current_Date + 1
RETURN
CALCULATE ( SUM ( Data[Earn Cum] ), Data[Date] = Next_Date )
Result:
Note: the code assumes that your dates are sequential (no gaps). If they have gaps, things are a bit more complex.
It will help to have access to date intelligence, so create a date table if you don't have one already. The following dax sets up a small table that just barely covers the sample data in your example.
Date = CALENDAR(Date(2019,4,10),Date(2019,5,5))
Create a relationship between the Dates in your table and the new Date dimension. Add a slicer to your visuals using the Date dimension.
We can use IF and ISFILTERED to check if filtering is being done. If we aren't filtering on Date then we get the normal table behavior. If we are, we'll see our modified result.
Earn _ Alt =
var tomorrow = CALCULATE (
SUM(Table1[Earn]),
dateadd('Table1'[Date], 1, DAY)
)
return Sum(Table1[Earn]) + IF(ISFILTERED`('Date'[Date]),tomorrow,0)`
and
Earn Cum. _ Alt = IF(ISFILTERED('Date'[Date]),
CALCULATE (
SUM(Table1[Earn Cum.]),
dateadd('Table1'[Date], 1, DAY)
),
SUM(Table1[Earn Cum.]))
Results:
-Unfiltered-
-Filtered-

X-Axis with Year and as well as Month Year for the near dates in the same graph

I have a dataset that contains monthly values over many years (grouped by month & other attributes so there can be multiple records for each month, although I don't think it matters for the problem) :
month val ...
1 2017-01-01 17.0700
2 2017-01-01 17.0700
3 2017-02-01 2.4432
.. ......... .....
4 2019-04-01 61.0800
5 2019-04-01 40.7200
6 2019-05-01 20.3600
I can properly visualize monthly data in a bar chart (month is recognized as a date hierarchy with Year and Month in the sub hierarchy)per year/month.
The issue I have is that because the data spans a large period of time, the chart is large and I would like to be able to reduce a year data (e.g. 2017,2018) to its monthly average.
The x axis of the result chart would be :
avg 2017 - avg 2018 - jan.2019 - feb. 2019 ...
The idea is to be able to drill down from a year monthly average back to the monthly values, although I do not know if this is possible?
I managed to get the years monthly average with the following measure :
year_monthly_avg =
AVERAGEX (
SUMMARIZE ( data, data[month] ),
CALCULATE ( SUM ( data[val] )
)
Which I can display in a separate bar chart (year in the axis).
The Idea is - To do this, you need another table derived from your existing table holding your x-axis values which is going to be on the graph.
I started with a data like this :-
Table 1
So, then lets generate the axis column (Calculated Column) on this Table1:-
AxisCol =
Var MaxYear = MAX((Table1[Date].[Year]))
Var Required_Year = YEAR(Table1[Date])
Var YearDiff = MaxYear - Required_Year
Var output = IF(YearDiff = 0, FORMAT(FORMAT(Table1[Date], "MMM YY"),"string"), FORMAT(Required_Year, "#"))
Return (output)
The data type of this AxisCol is "Text".
Generate the Month Year and Year Column (Calculated Column) in Table 1
Month Year = FORMAT(Table1[Date], "MMM YY")
Year = YEAR(Table1[Date])
Set the data type of these two columns as "Text" as well.
Create a new table :-
Axis_Table = DISTINCT(Table1[AxisCol])
This has now created the disconnected table.
Now, Create the Date_Col (Calculated Column) to find the Sort Order inside the Axis_Table.
Date_col =
Var RequiredVal = VALUE(Axis_Table[AxisCol])
Var Year_or_Month_year = IF(LEN(RequiredVal) = 4, "Year", "Month Year")
Var year_split = VALUE("20" & RIGHT(Axis_Table[AxisCol],2))
Var Month_split = (LEFT(Axis_Table[AxisCol],3))
Var month_num = SWITCH(Month_split, "Jan", 1, "Feb", 2, "Mar", 3, "Apr"
, 4, "May", 5, "Jun", 6, "Jul", 7, "Aug"
, 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec"
, 12)
Var myDate = if(Year_or_Month_year = "Year",DATE(RequiredVal,1,1),DATE(year_split, month_num,1))
Return myDate
Now, you can create the Sort Order (Calculated Column) in Axis_Table
Sort Order = DATEDIFF((Axis_Table[Date_col]),MAX(Axis_Table[Date_col]),MONTH)
Now the final output as a Measure,
ValueReq =
var required_axis_val = SELECTEDVALUE(Axis_Table[AxisCol])
Var requiredaxis = LEN(required_axis_val)
Var output1 = CALCULATE(AVERAGE(Table1[Value]), FILTER(Table1,Table1[Month Year] = required_axis_val))
Var output2 = CALCULATE(AVERAGE(Table1[Value]),FILTER(Table1, Table1[Year] = required_axis_val))
var out_req = IF(requiredaxis = 4, output2, output1)
return out_req
This measure can be altered as per your filter selections and other conditions that you might have.
The Final Visual looks like this,
Use the Sort Order in Tooltips and then Sort the axis inside the visual by Sort Order.
You can then create a relationship between the tables on the axis_col for your slicers to work.
You can then differentiate the axis with conditional formatting using this -
conditional formatting = IF(LEN(SELECTEDVALUE(Axis_Table[AxisCol])) = 4,1,0)
Let me know, if you are struggling to understand the solution.
Accept the answer if you can get it to work for you.

Circular Dependency Calculated Column Power BI Desktop

In my Calculated Table, variable AsOfDate should be reflected by slicer dim_Date which is also calculated table.
Calculated table CrossTableEffectiveDate derived from table fact_Premium that have Date relationship to dim_Date.
I got error: Circular Dependency Calculated Column
CrossTableEffectiveDate =
VAR AsOfDate = VALUE("2019-01-31") //This value should be based on date value in a slicer
VAR CrossTables =
CROSSJOIN(
SUMMARIZE(fact_Premium,
fact_Premium[PolicyNumber],
fact_Premium[CompanyLocationGuid],
fact_Premium[Coverage],
fact_Premium[State],
fact_Premium[SICCode],
fact_Premium[ASLOB],
fact_Premium[ProducerGUID],
"Start", MIN(fact_Premium[EffectiveDate]),
"End", MAX(fact_Premium[ExpirationDate]),
"Premium", SUM(fact_Premium[Premium])
),
'Calendar')
VAR RiskPeriods =
ADDCOLUMNS(
FILTER(CrossTables,
'Calendar'[EoMonth] >= [Start] && 'Calendar'[Month] <= [End] && 'Calendar'[Month] <= AsOfDate),
"StartRiskMonth", IF([Start] > 'Calendar'[Month], [Start], 'Calendar'[Month]),
"EndRiskMonth", IF([End] < 'Calendar'[EoMonth], [End], 'Calendar'[EoMonth])
)
RETURN SELECTCOLUMNS(RiskPeriods,
"PolicyNumber", fact_Premium[PolicyNumber],
"CompanyLocationGUID", fact_Premium[CompanyLocationGuid],
"Coverage",fact_Premium[Coverage],
"State", fact_Premium[State],
"SICCode",fact_Premium[SICCode],
"ASLOB", fact_Premium[ASLOB],
"ProducerGUID",fact_Premium[ProducerGUID],
"StartRiskMonth", [StartRiskMonth],
"EndRiskMonth", [EndRiskMonth],
"YearNum", YEAR('Calendar'[Month]),
"Qtr", ROUNDUP(MONTH('Calendar'[Month])/3, 0),
"MonthNum", MONTH('Calendar'[Month]),
"WrittenPremium", [Premium],
"DaysInMonth", [EndRiskMonth] - [StartRiskMonth] + 1,
//"EndRiskMonth-Start", [EndRiskMonth] - [StartRiskMonth] + 1,
//"End-Start",[End] - [Start] + 1,
"EarnedPremium", [Premium] *
DIVIDE([EndRiskMonth] - [StartRiskMonth] + 1, [End] - [Start] + 1))
How can I make AsOfDate variable be referenced by Date slicer from dim_Date?
You cannot have a calculated table or calculated column be dependent on a slicer.
These are only calculated once per data load and are not responsive to any filtering you have in your report.
You can add your support to this idea to improve the chances of Microsoft implementing it.
Dynamic calculated column

How to check if current start and end dates are in previous period (start and end dates)

I have a tricky problem I am working on. I've made several attempts at capturing the data but have been unsuccessful.
I have a table in Power Bi that looks like this:
The key is in ascending order as well as the StartDate field. I would like to achieve the results in the "Period Overlap Delta" field but have had trouble trying to figure it out.
Basically, I'd like to assign a value of zero to any period (startdate-enddate combination) that is IN a previous period and take the date difference of those "super" periods.
Here is the DAX to produce the table:
Cases = DATATABLE("Key", integer, "StartDate", datetime, "EndDate", datetime
,{
{1, "01/01/2018", "01/10/2018"}
, {2, "01/03/2018","01/03/2018"}
, {3, "01/05/2018","01/07/2018"}
, {4, "01/15/2018","01/16/2018"}
, {5, "01/21/2018","01/24/2018"}
, {6, "01/25/2018", "01/27/2018"}
, {7, "01/25/2018","01/27/2018"}
})
Thanks so much in advance!!!
We need to know whether or not a certain row is overlapped by a previous row. By previous we mean the key is smaller than current row. By overlapped we mean the StartDate is earlier or equal to current row and EndDate is later or equal to current row, hence:
Overlapped =
COUNTROWS(
FILTER(
'Cases',
'Cases'[StartDate] <= EARLIER('Cases'[StartDate]) &&
'Cases'[EndDate] >= EARLIER('Cases'[EndDate]) &&
'Cases'[Key] < EARLIER('Cases'[Key])
)
)
And with this we just need to wrap it up and calculate the number of days with the DATEDIFF function:
Period Overlap Delta =
VAR Overlapped =
COUNTROWS(
FILTER(
'Cases',
'Cases'[StartDate] <= EARLIER('Cases'[StartDate]) &&
'Cases'[EndDate] >= EARLIER('Cases'[EndDate]) &&
'Cases'[Key] < EARLIER('Cases'[Key])
)
)
RETURN
IF(Overlapped, 0, DATEDIFF('Cases'[StartDate], 'Cases'[EndDate], DAY) + 1)
P.S. The use of DATATABLE to provide sample data is golden and should be promoted more often!