Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
GZavela
Regular Visitor

Calculate count of specific customers who are new, lost, or returning customers

Hello,

 

I am trying to figure out how to calculate which of our customers are new customers, lost customers, and returning customers over a period of time.  For example, over the past 4 years I want to see how many customers are new, by year/month, how many customers we have lost, by year/month, and how many are returning by year month.

 

The criteria is:

 

New customers - Customers who have not purchased anything in the entirety of the previous year in total (not year/month), but have purchased something in the "current" year/month

 

Lost customers - Customers who have purchased something in the entirety of the previous year, but not the "current" year/month

 

Returning customers - Customers who have purchased something for the entirety of the previous year, and the "current" year/month

 

This would need to be over multiple years, and year/months.  The example below is what the data would look like if a customer has purchased something over a course of 4 year:

 

CustomerPosting DateDocument No
C100001/1/2015SI000001
C100004/1/2015SI000002
C100003/16/2016SI000003
C100001/1/2018SI000005
C100011/1/2016SI000006
C100015/1/2017SI000007
C1000112/4/2018SI000008
C100021/5/2018SI000008
C100031/1/2015SI000009
C100034/8/2016SI000010
C100033/15/2017SI000011
C1000312/13/2018SI000012
C100041/1/2016SI000013
C1000412/4/2018

SI000014

 

Based on the data above, the customer status would be as described below for the 4 year period of time:

 

CustomerCustomer Status
C10000New customer for 2015
 Returning customer for 2016
 Lost customer for 2017
 New customer for 2018
C10002New customer for 2018
C10003New customer for 2015
 Returning customer for 2016
 Returning customer for 2017
 Returning customer for 2018
C10004New customer for 2016
 New customer for 2018

 

Based on the two sets of data above, if I were to create a pivot table it should look like the example below:

 

 YearMonth                                              
 2015           2016           2017           2018           
Customer StatusJanFebMarAprMayJunJulAugSepOctNovDecJanFebMarAprMayJunJulAugSepOctNovDecJanFebMarAprMayJunJulAugSepOctNovDecJanFebMarAprMayJunJulAugSepOctNovDec
Count of New Customers2           2                       2          1
Count of Lost Customers                                                
Count of Returning Customers              11          1 1                  2

 

I am unable to attach the workbook example, so let me know if something does not make sense, or is unclear, and thank you in advance!

 

1 ACCEPTED SOLUTION
AkhilAshok
Solution Sage
Solution Sage

You can follow the below steps:

 

1. Create a Date table and add a relationship between Date[Date] & Purchase[Posting Date]. If you don't have one, you can use the sample logic below:

Date = 
VAR BaseCalendar =
    CALENDAR ( MIN(Purchase[Posting Date]), MAX(Purchase[Posting Date]) )
RETURN
    GENERATE (
        BaseCalendar,
        VAR BaseDate = [Date]
        VAR YearDate = YEAR ( BaseDate )
        VAR MonthNumber = MONTH ( BaseDate )
        RETURN ROW (
            "Year", YearDate,
            "Month Number", MonthNumber,
            "Month", FORMAT ( BaseDate, "mmm" )
        )
    )

2. Create the following measures:

New Customer = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentCustomers =
    CALCULATETABLE ( VALUES ( Purchase[Customer] ), ALL ( 'Date'[Date] ))
VAR PreviousCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        FILTER (
            ALL ( 'Date' ),
            'Date'[Year] = CurrentYear - 1
                || ( 'Date'[Year] = CurrentYear
                && 'Date'[Month Number] < CurrentMonth )
        )
    )
VAR NewCustomers =
    EXCEPT ( CurrentCustomers, PreviousCustomers )
RETURN
    COUNTROWS ( NewCustomers )
Lost Customers = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALLEXCEPT ( 'Date', 'Date'[Year] )
    )
VAR PreviousYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALL ( 'Date' ),
        'Date'[Year] = CurrentYear - 1
    )
VAR LostCustomers =
    EXCEPT ( PreviousYearCustomers, CurrentYearCustomers )
VAR IsYearGrain =
    NOT ( ISFILTERED ( 'Date'[Month] ) || ISFILTERED ( 'Date'[Date] ) )
RETURN
    IF ( IsYearGrain, COUNTROWS ( LostCustomers ) )
Returning Customers = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentCustomers =
    CALCULATETABLE ( VALUES ( Purchase[Customer] ), ALL ( 'Date'[Date] ) )
VAR PreviousYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALL ( 'Date' ),
        'Date'[Year] = CurrentYear - 1
    )
VAR ReturningCustomers =
    INTERSECT ( PreviousYearCustomers, CurrentCustomers )
RETURN
    COUNTROWS ( ReturningCustomers )

From you requirement, I see that Lost customers you only want to display at Year grain?

 

Let me know if this works for you.

View solution in original post

3 REPLIES 3
AkhilAshok
Solution Sage
Solution Sage

You can follow the below steps:

 

1. Create a Date table and add a relationship between Date[Date] & Purchase[Posting Date]. If you don't have one, you can use the sample logic below:

Date = 
VAR BaseCalendar =
    CALENDAR ( MIN(Purchase[Posting Date]), MAX(Purchase[Posting Date]) )
RETURN
    GENERATE (
        BaseCalendar,
        VAR BaseDate = [Date]
        VAR YearDate = YEAR ( BaseDate )
        VAR MonthNumber = MONTH ( BaseDate )
        RETURN ROW (
            "Year", YearDate,
            "Month Number", MonthNumber,
            "Month", FORMAT ( BaseDate, "mmm" )
        )
    )

2. Create the following measures:

New Customer = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentCustomers =
    CALCULATETABLE ( VALUES ( Purchase[Customer] ), ALL ( 'Date'[Date] ))
VAR PreviousCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        FILTER (
            ALL ( 'Date' ),
            'Date'[Year] = CurrentYear - 1
                || ( 'Date'[Year] = CurrentYear
                && 'Date'[Month Number] < CurrentMonth )
        )
    )
VAR NewCustomers =
    EXCEPT ( CurrentCustomers, PreviousCustomers )
RETURN
    COUNTROWS ( NewCustomers )
Lost Customers = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALLEXCEPT ( 'Date', 'Date'[Year] )
    )
VAR PreviousYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALL ( 'Date' ),
        'Date'[Year] = CurrentYear - 1
    )
VAR LostCustomers =
    EXCEPT ( PreviousYearCustomers, CurrentYearCustomers )
VAR IsYearGrain =
    NOT ( ISFILTERED ( 'Date'[Month] ) || ISFILTERED ( 'Date'[Date] ) )
RETURN
    IF ( IsYearGrain, COUNTROWS ( LostCustomers ) )
Returning Customers = 
VAR CurrentYear =
    MAX ( 'Date'[Year] )
VAR CurrentMonth =
    MAX ( 'Date'[Month Number] )
VAR CurrentCustomers =
    CALCULATETABLE ( VALUES ( Purchase[Customer] ), ALL ( 'Date'[Date] ) )
VAR PreviousYearCustomers =
    CALCULATETABLE (
        VALUES ( Purchase[Customer] ),
        ALL ( 'Date' ),
        'Date'[Year] = CurrentYear - 1
    )
VAR ReturningCustomers =
    INTERSECT ( PreviousYearCustomers, CurrentCustomers )
RETURN
    COUNTROWS ( ReturningCustomers )

From you requirement, I see that Lost customers you only want to display at Year grain?

 

Let me know if this works for you.

Hi.  I love how elegant the code is...but I'm getting some wonky results.    Note "Card Name" as my field for the unique name.    Otherwise, I'm using 100% the code for the # customers that have transacted in the prior 12 mos, and 99% of the same code for customers that have transacted in the prior month (just adding an additional filter).

 

/12Mo_RepeatCusts_By#/:=	
VAR CurrentYear =	
    MAX ( 'Date'[Year] )	
VAR CurrentMonth =	
    MAX ( 'Date'[Month Number] )	
VAR CurrentCustomers =	
    CALCULATETABLE ( VALUES ( Table1[Card Name]), ALL ( 'Date'[Date] ) )	
VAR PreviousYearCustomers =	
    CALCULATETABLE (	
        VALUES ( Table1[Card Name] ),	
        ALL ( 'Date' ),	
        'Date'[Year] = CurrentYear - 1	
    )	
VAR ReturningCustomers1Yr =	
    INTERSECT ( PreviousYearCustomers, CurrentCustomers )	
RETURN	
    COUNTROWS ( ReturningCustomers1Yr )	

 

/1Mo_RepeatCusts_By#/:=			
VAR CurrentYear =			
    MAX ( 'Date'[Year] )			
VAR CurrentMonth =			
    MAX ( 'Date'[Month Number] )			
VAR CurrentCustomers =			
    CALCULATETABLE ( VALUES ( Table1[Card Name]), ALL ( 'Date'[Date] ) )			
VAR PreviousMonthCustomers =			
    CALCULATETABLE (			
        VALUES ( Table1[Card Name] ),			
        ALL ( 'Date' ),			
        	'Date'[Year] = CurrentYear, 		
        	'Date'[Month Number] = CurrentMonth - 1  		
        	  )		
VAR ReturningCustomers1Mo =			
    INTERSECT ( PreviousMonthCustomers, CurrentCustomers )			
RETURN			
    COUNTROWS ( ReturningCustomers1Mo )			

The results are wonky because, for many periods, I get more customer who transacted in the prior month than in the prior year.  Possibly, I have messed up by 1Mo Repeat Customer adaptation.  Could it be, however, that the measures above have a problem because they are absolute rather than relative?  Ie they peg to a year and a prior year whereas the best measure should be 365 days or 30 days?

 

I apologize for not including my file.   I'm using excel power pivot not PBIX and have some PII in the files

 

 

 

 

 

 

A sample data which illustrastes the issue would be helpful. Meanwhile, for getting previous month customers a better approach would be following:

VAR PreviousMonthCustomers =
CALCULATETABLE ( VALUES ( Table1[Card Name] ), PREVIOUSMONTH ( 'Date'[Date] ) )

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.