Table of starting dates of each month in PBI - powerbi

How to extract from Calendar table or how to generate from scratch a one column table containing only the first day of each month.
I can think of this:
SUMMARIZE(
'Calendar',
'Calendar'[Date].[Year],
'Calendar'[Date].[Month],
"minDate", MIN('Calendar'[Date])
)
Of that I need only the column minDate. Could there be any simpler or more efficient way to generate such series of starting month dates?
The problem with my query is that it is 3 columns, not one.

To generate from scratch:
first_day_of_month =
DISTINCT (
SELECTCOLUMNS (
SUMMARIZE (
CALENDAR ( DATE ( 2019, 1, 1 ), DATE ( 2019, 04, 01 ) ),
[Date],
"x", DATE ( YEAR ( [Date] ), MONTH ( [Date] ), 1 )
),
"first_day_of_month", [x]
)
)
A bit cleaner:
first_day_of_month =
GROUPBY (
SUMMARIZE (
CALENDAR ( DATE ( 2019; 1; 1 ); DATE ( 2019; 04; 01 ) );
[Date];
"first_day_of_month"; DATE ( YEAR ( [Date] ); MONTH ( [Date] ); 1 )
);
[first_day_of_month]
)

You can use SELECTCOLUMNS to return a table with only the column that you need.
SELECTCOLUMNS(
SUMMARIZE(
'Calendar',
'Calendar'[Date].[Year],
'Calendar'[Date].[Month],
"minDate", MIN('Calendar'[Date])
),
"minDate", [minDate])

Related

Prev years YTD sales Dax formula

I am having some difficulties in creating a dax formula for calculating prev yr YTD sales.
I have written a formula but the same is not working.
I need to calculate the performance % yr over yr by comparing YTD sales of current year to YTD of prev yr sales.
any help would be appreciated
Sales sameperiod =
VAR first_date =
FIRSTDATE ( DATEADD ( 'Date'[Date], -12, MONTH ) )
VAR last_date =
LASTDATE ( DATEADD ( 'COGS Data'[Invoice Date], -12, MONTH ) )
RETURN
IF (
ISBLANK ( first_date ) || ISBLANK ( last_date ),
BLANK (),
CALCULATE (
SUM ( 'COGS Data'[Final Unit Cost] ),
DATESBETWEEN ( 'Date'[Date], first_date, last_date )
)
)
there are multiple ways, but my go-to is creating a Date table, I assume you already have it.
Then you would create relationship to Fact table from DateKey, and a new matrix visual with rows from Date Table, for example Date and Month. And Measure would be like -
Revenue last year = IF(
HASONEVALUE ('Date'[Month]),
IF (
SUM ('COGS Data'[Final Unit Cost] ) <> BLANK(),
CALCULATE (
SUM ( 'COGS Data'[Final Unit Cost] ),
SAMEPERIODLASTYEAR ('Date'[Date])
)
),
CALCULATE (
SUM ( 'COGS Data'[Final Unit Cost] ),
DATESBETWEEN (
'Date'[Date],
EDATE ( MIN ('Date'[Date]), -12 ),
EDATE ( MAX ('COGS Data'[Invoice Date]), -12 )
)

Tabular DAX - best way to get min date in calendar regardless of context

I have a typical rolling 12 months Dax measure as :
R12M :=
CALCULATE (
[Income],
DATESBETWEEN (
Calendar[Date],
NEXTDAY ( SAMEPERIODLASTYEAR ( LASTDATE ( Calendar[Date] ) ) ),
LASTDATE ( 'Calendar'[Date] )
)
)
The problem is that our Calendar table only starts from a certain date, so anything which is in the first year does not link to the calendar. So I want to start the measure from a year after the minimum date on our calendar. What is the best way to achieve this?
I hope you found your answer by now, but in case still looking then try like,
R12M :=
CALCULATE (
[Income],
DATESBETWEEN (
Calendar[Date],
NEXTDAY ( SAMEPERIODLASTYEAR ( LASTDATE ( Calendar[Date] ) ) ),
LASTDATE ( 'Calendar'[Date] )
),
FILTER ( CALENDER, DATE >= DATEADD ( FIRSTDATE ( DATE ), 1, YEAR ) )
)

DAX Convert date to the first day of quarter

While building a calendar table I came across unexpected hard nut to crack.
How to convert date to the first date of the quarter? Here are some examples:
2019-02-01 > 2019-01-01
2019-03-31 > 2019-01-01
2019-04-02 > 2019-04-01
The function STARTOFQUARTER does not work in my calendar. I do not know why.
Calendar =
GENERATE (
CALENDAR (
DATE ( 2016, 1, 1 ),
DATE ( 2020, 12, 31 )
),
VAR VarDates = [Date]
var YQ_date = STARTOFQUARTER( [Date] ) -- this does not work
RETURN
ROW (
"day" , VarDay,
"YQ_date" , YQ_date
)
)
The only option seems to be adding calculated column to Calendar table. But if it is possible to have it straight, then why not have it straight?
How about as an added column?
Calendar =
ADDCOLUMNS (
CALENDAR ( DATE ( 2016, 1, 1 ), DATE ( 2020, 12, 31 ) ),
"YQ_date", EOMONTH ( [Date], -1 - MOD ( MONTH ( [Date] ) - 1, 3 ) ) + 1
)
For the STARTOFQUARTER function to work, you need the dates that you expect to be returned by the function in your datetable.
So in the provided sample, you need to add the dates 2019-01-01 and 2019-04-01.
Something like this:
When you want to build a calendar table with one DAX expression, you cannot use the STARTOFQUARTER function, because it will not work with an in-memory table.
You could use something like this as a workaround though:
Calendar =
GENERATE (
CALENDAR (
DATE ( 2016; 1; 1 );
DATE ( 2020; 12; 31 )
);
ROW (
"YQ_date"; DATE( Year( [Date] ); ROUNDUP( MONTH ( [Date] ) / 3; 0 ) * 3 - 2; 1)
)
)

DAX time intelligence functions with nested filters

I have a data structure like this
DateRoll Dataset Date Value Customer
Month Online 1/1/2018 10 Cust1
Month Online 2/1/2018 11 Cust1
Month Online 3/1/2018 12 Cust1
Month Online 4/1/2018 22 Cust1
Quarter Online 1/1/2018 33 Cust1
Quarter Online 4/1/2018 22 Cust1
I have to calculate previous quarter value, I tried different ways but it's not working
1 - Not returning any value.
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, QUARTER ),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter")
)
2--Nested - Returning overall total
CALCULATE (
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, QUARTER )
),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter" )
)
3--Nested --Returning overall total
CALCULATE (
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter" )
),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, MONTH )
)
Tried PREVIOUSQUARTER function too, but its not returning any value.
To take advantage of built in DAX time intelligence functions you will need to to have a contiguous set of dates. I would recommend using a date table. The following code can be used to create a date/calendar table in your model:
Celndar =
Var MinDate = MIN(Data_Rollup_KPI_DNR[Date])
Var MaxDate = MAX(Data_Rollup_KPI_DNR[Date])
Var BaseCalendar = CALENDAR(MinDate, MaxDate)
RETURN
GENERATE (
BaseCalendar,
VAR BaseDate = [Date]
VAR YearDate =
YEAR ( BaseDate )
VAR MonthNumber =
MONTH ( BaseDate )
VAR YrMonth =
100 * YEAR ( BaseDate )
+ MONTH ( BaseDate )
VAR Qtr =
CONCATENATE ( "Q", CEILING ( MONTH ( BaseDate ) / 3, 1 ) )
RETURN
ROW (
"Day", BaseDate,
"Year", YearDate,
"Month Number", MonthNumber,
"Month", FORMAT ( BaseDate, "mmmm" ),
"Year Month", FORMAT ( BaseDate, "mmm yy" ),
"YrMonth", YrMonth,
"Qtr", Qtr
)
)
Once this table exists, mark it as a 'date' table and create a relationship with
Data_Rollup_KPI_DNR[Date]
Then, you can write the following measure to obtain the results you are searching for:
PQSum =
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
PREVIOUSQUARTER ( 'Calendar'[Date] )
)
Hope that helps!
*Edited
You can also create a ranking column to index in a measure:
Rank =
RANKX (
FILTER (
'Data_Rollup_KPI_DNR',
'Data_Rollup_KPI_DNR'[DateRoll] = EARLIER ( 'Data_Rollup_KPI_DNR'[DateRoll] )
),
'Data_Rollup_KPI_DNR'[Date].[Date],
,
ASC
)
Then you can reference a previous quarter using something like the following:
PQSum2 =
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
FILTER (
'Data_Rollup_KPI_DNR',
'Data_Rollup_KPI_DNR'[Rank]
= MAX ( 'Data_Rollup_KPI_DNR'[Rank] ) - 1
),
'Data_Rollup_KPI_DNR'[DateRoll] = "Quarter"
)
but this is hard coded and just plain nasty!
Echoing #steliok that a date dimension is the proper way to handle this; there are plenty of date table templates out there, and a date dimension will work with your data model. If you really really can't add to your data structure for some reason, this should work:
BaseValue = SUM ( 'Data_Rollup_KPI_DNR'[Value] )
PriorQuarter =
VAR CurrentDate = MAX ( 'Data_Rollup_KPI_DNR'[Date] )
VAR CurrentYear = YEAR ( CurrentDate )
VAR CurrentMonth = MONTH ( CurrentDate )
VAR FirstMonthOfCurrentQuarter =
SWITCH (
TRUE (),
CurrentMonth IN {1,2,3}, 1,
CurrentMonth IN {4,5,6}, 4,
CurrentMonth IN {7,8,9}, 7,
CurrentMonth IN {10,11,12}, 10
)
// DATE() does the right thing with negative month args
VAR PriorQuarterDate = DATE ( CurrentYear, FirstMonthOfCurrentQuarter - 3, 1 )
RETURN
CALCULATE (
[BaseValue],
ALL ( 'Data_Rollup_KPI_DNR'[DateRoll], 'Data_Rollup_KPI_DNR'[Date] ),
'Data_Rollup_KPI_DNR'[Date] = PriorQuarterDate,
'Data_Rollup_KPI_DNR'[DateRoll] = "Quarter"
)
This relies on DATE being clever, which it is. DATE ( 2019, -2, 1 ) = DATE ( 2018, 10, 1 ).
Ultimately, my question is why can't you just source the un-rolled up data from the same place that the ETL process is sourcing it?
Date functions are working well when you are using # Day level.
Following link would be helpful to resolve your issue,
https://community.powerbi.com/t5/Desktop/Lead-and-Lag-in-DAX/td-p/649162

DAX Measure to Calculate Percentage of Customers with New Purchases Within One Year Sliding Window

I need a measure that will give me the percentage of customers during a calendar year who had new purchases within one year of their last purchase.
Normally I would just create a calculated column that captured the date of each customer's last purchase for each year, and then check to see if each customer from a given year had any purchases within a year of their respective last date, and then sum those up, but I'm using a live connection to a cube and can't create calculated columns.
Here's some pseudo-code of what I'm looking for:
One Year Return =
VAR Cohort =
SUMMARIZECOLUMNS (
Customer[ID],
FILTER (
VALUES ( Sales[Sales Date] ),
YEAR ( Sales[Sales Date] )
< ( YEAR ( TODAY () ) - 1 )
)
)
VAR Returners =
SUMMARIZECOLUMNS (
Customer[ID],
FILTER (
VALUES ( Sales[Sales Date] ),
Sales[Sales Date] > Sales[Old Sales Date] //<--Need help here
),
FILTER (
VALUES ( Customer[ID] ),
Customer[ID] IN Cohort
)
)
VAR Rate =
CALCULATE ( DISTINCTCOUNT ( Customer[ID] ), Customer[ID] IN Returners ) /
CALCULATE ( DISTINCTCOUNT ( Customer[ID] ), Customer[ID] IN Cohort )
RETURN
Rate
The main difficulty is that I need a different time window for each customer, but can't make a calculated column. I've been looking at using EARLIER or DATESBETWEEN or PARALLELPERIOD, but haven't been able to get any of them to work so far.
First I think you are looking for this
VAR last_year = DATE ( YEAR ( TODAY () ) - 1; MONTH ( TODAY () ); DAY ( TODAY () ) )
Second. The best way to get this done you need a bit of data modeling. The only way to make time intelligence work is to have a Date table. This table should have a row by day without missing days. You can search online how to create one or check my blog here.
Once you have this table releated on your model with your fact table you will be able to build that measure on a selected date. The selected one will be a value and last year of selected value the other one.
The crux is in the fact that you need to compare for each customer without a calculated column. It is possible by using the an iterator like COUNTX or SUMX. This enables you to loop through your customers in the cohort sub-table and create selections of your sales table by using the customer ID in the current iteration to filter your sales table using EARLIER. For each customer in the cohort you then select their last purchase date and the one before that and compare the two to see if they followed within the year.
In DAX it looks a bit complex but I tried to make it spacier so it is easier to follow. It also contains a little workaround for the fact that you cannot simply loop over the _cohort variable as you won't have access to the customer ID in the current iteration in that case
One year return =
var _now = TODAY()
var _cohort =
SUMMARIZECOLUMNS (
Sales[CustomerID] ;
FILTER (
Sales ;
DATEDIFF( Sales[SalesDate] ; _now ; YEAR ) <= 1
)
)
var _countCohort = COUNTROWS( _cohort )
var _countReturns =
SUMX (
SUMMARIZECOLUMNS (
Sales[CustomerID] ; FILTER ( Sales ; Sales[CustomerID] IN _cohort )
) ;
var _lastPurchase =
CALCULATE (
MAX ( Sales[SalesDate] ) ;
ALLSELECTED ( Sales ) ;
Sales[CustomerID] = EARLIER( Sales[CustomerID] )
)
var _preLastPurchase =
CALCULATE (
MAX ( Sales[SalesDate] ) ;
ALLSELECTED ( Sales ) ;
Sales[SalesDate] < _lastPurchase ;
Sales[CustomerID] = EARLIER( Sales[CustomerID] )
)
RETURN
IF ( DATEDIFF( _preLastPurchase ; _lastPurchase ; YEAR ) <= 1 ; 1 ; 0 )
)
RETURN
_countReturns / _countCohort
I ended up importing a dataset from the cube and creating calculated columns to get me there after all. #jelle-hoekstra's answer looks close to what I ended up doing, but I couldn't figure out how to get his measure to run.
I made three calculated columns and did a distinct count on the ReturnCustomerID column to get the number of customers who returned within one year of their last purchase:
Last Purchase Date =
MINX (
FILTER (
Sales,
Sales[Sales Year]+1 = EARLIER ( Sales[Sales Year] ) && Sales[CustomerID] = EARLIER ( Sales[CustomerID] )
),
MAXX (
FILTER (
Sales,
Sales[Sales Year] = EARLIER ( Sales[Sales Year] ) && Sales[CustomerID] = EARLIER ( Sales[CustomerID] )
),
Sales[Sales Date]
)
)
One Year Date =
MINX (
FILTER (
Sales,
Sales[Sales Year]+1 = EARLIER ( Sales[Sales Year] ) && Sales[CustomerID] = EARLIER ( Sales[CustomerID] )
),
MAXX (
FILTER (
Sales,
Sales[Sales Year] = EARLIER ( Sales[Sales Year] ) && Sales[CustomerID] = EARLIER ( Sales[CustomerID] )
),
EDATE (Sales[Sales Date], 12 )
)
)
ReturnCustomerID =
IF (
Sales[Sales Date] > Sales[Last Purchase Date] && Sales[Sales Date] < Sales[One Year Date], Sales[CustomerID], BLANK()
)