This month's Harvard Business Review (HBR) article Stop Trying to Delight Your Customers argues that companies should focus on meeting their customers' needs rather than trying to provide over-the-top service to increase tenure and customer loyalty. The latter doesn't translate into increased loyalty and efforts toward it are usually at the expense of the former.
Customers notoriously punish bad service, particularly when left on hold, transferred while on a service call, or when they receive egregious customer service. We've all been there and we've all told two friends and two friends and so on. Customers share negative experiences at twice the rate of positive ones, according to a customer service and loyalty study from the Customer Contact Council. What's more, reducing customers' efforts builds loyalty, the vague notion of delighting them does not. Customers want their problem solved, not some whiz-bang, over the top widget. And finally, improved customer service, particularly in the call-to-contact realm does more to reduce churn than the "delight them" efforts. Maybe, the "delight them" focus should be on the customers' experience rather than delight in the company's product.
What are your thoughts on customer service and the customer experience? Do you want to be delighted or are you often disappointed because your core services needs are unmet?
Tuesday, August 3, 2010
Tuesday, July 27, 2010
Calculating Tenure when your Cancel Date is in the future
A configuration on our EComm system requires that every subscriber have a NOT NULL Cancel Date. This presented some difficulty for calculating tenure, particularly since the default for paying subscribers is 2999-01-01. Wow! That's some great tenure. They've been paying subscribers longer than we've been in business.
For the past few weeks I've been grappling with how to adjust the CancelDt and calculate tenure. Since I'm using Tableau on top of Teradata, I've dug into both and decided on the below.
These calculations are included in a monthly churn workbook I produce for our product team. The workbook is updated at the beginning of each month and analyzes churn and media adoption for the previous month, it's preceding three month average, and the same periods in the previous year. The dates are configured to update dynamically, so the current_date assignment is valid for the entire month the workbook is valid. Once the workbook updates for the following month, you'll be ahead and the current_date assignment will remain in the month ahead of the study month.
Previous method for adjusting the CancelDt and calculating churn:
In Teradata create a view or use custom query for Tableau
Then in Tableau, create a custom metrics to resolve the future date
"CancelMo Truncated"
IIF([CancelMo] > TODAY(), DATETRUNC('month',TODAY()),[CancelMo])
and to calculate "Tenure"
DATEDIFF('month',[SignupMo],[CancelMo Truncated])
Updated Method
Push it all back to the database:
select RptMonth
, Id
, SignupDt
, CASE WHEN CancelDt = '2999-01-01' THEN current_date ELSE CancelDt END CancelDtUpd
, (CancelDtUpd - SignupDt) month(4) as Tenure
, CASE WHEN CancelDt = '2999-01-01' THEN 1 ELSE 0 END PayingFlag
from foo
For the past few weeks I've been grappling with how to adjust the CancelDt and calculate tenure. Since I'm using Tableau on top of Teradata, I've dug into both and decided on the below.
These calculations are included in a monthly churn workbook I produce for our product team. The workbook is updated at the beginning of each month and analyzes churn and media adoption for the previous month, it's preceding three month average, and the same periods in the previous year. The dates are configured to update dynamically, so the current_date assignment is valid for the entire month the workbook is valid. Once the workbook updates for the following month, you'll be ahead and the current_date assignment will remain in the month ahead of the study month.
Previous method for adjusting the CancelDt and calculating churn:
In Teradata create a view or use custom query for Tableau
select RptMonth , Id , SignupDt - (EXTRACT(DAY from SignupDt) -1) as SignupMo , CancelDt - (EXTRACT(DAY from CancelDt) -1) as CancelMo from foo
Then in Tableau, create a custom metrics to resolve the future date
"CancelMo Truncated"
IIF([CancelMo] > TODAY(), DATETRUNC('month',TODAY()),[CancelMo])
and to calculate "Tenure"
DATEDIFF('month',[SignupMo],[CancelMo Truncated])
Updated Method
Push it all back to the database:
select RptMonth
, Id
, SignupDt
, CASE WHEN CancelDt = '2999-01-01' THEN current_date ELSE CancelDt END CancelDtUpd
, (CancelDtUpd - SignupDt) month(4) as Tenure
, CASE WHEN CancelDt = '2999-01-01' THEN 1 ELSE 0 END PayingFlag
from foo
Wednesday, May 12, 2010
Date Formats in Tableau
ddd - Short Day of Week (ex., Mon)
mmm - 3 Letter Month (ex., Jan)
MMMM - Full Month (ex., January)
d - short digit of month (7, not 07)
DDDD - Weekday (ex., Monday)
DD - Day (01, not 1)
yyyy - 4 digit year
yy - 2 digit year
q - quarter (Q)
w - week (W)
mmm - 3 Letter Month (ex., Jan)
MMMM - Full Month (ex., January)
d - short digit of month (7, not 07)
DDDD - Weekday (ex., Monday)
DD - Day (01, not 1)
yyyy - 4 digit year
yy - 2 digit year
q - quarter (Q)
w - week (W)
Wednesday, December 23, 2009
Teradata - Secondary Index
Two challenges for this week:
1. How to create a volatile table with a secondary index
2. How to add an index to an existing table.
While there is no secondary index explicit in TD for VOLATILE tables, I found that I could simply add indices after the PRIMARY INDEX and voila:
CREATE VOLATILE TABLE FOO
(
Id INT
, Date DATE
, Product VARCHAR(20)
)
PRIMARY INDEX (Id)
INDEX (Product)
ON COMMIT PRESERVE ROWS; -- to ensure when you populate the table you can query the data.
Adding a Secondary Index (unique or non-unique) to an existing table:
create index index_name (Field) on database.table;
1. How to create a volatile table with a secondary index
2. How to add an index to an existing table.
While there is no secondary index explicit in TD for VOLATILE tables, I found that I could simply add indices after the PRIMARY INDEX and voila:
CREATE VOLATILE TABLE FOO
(
Id INT
, Date DATE
, Product VARCHAR(20)
)
PRIMARY INDEX (Id)
INDEX (Product)
ON COMMIT PRESERVE ROWS; -- to ensure when you populate the table you can query the data.
Adding a Secondary Index (unique or non-unique) to an existing table:
create index index_name (Field) on database.table;
Tuesday, November 3, 2009
Extracting the Day of Week to roll up cohorts into Discrete Weeks
Dates seem to be a common theme for me. I'm sure I'm not alone. Today I'm working on a project where I need to group all people into a calendar week for their event. Thus, I want to take their Event Date, extract AND subtract the DayOfWeek from the Event Date to group everyone by the week's first day.
Also, we calculate our weeks as Monday - Sunday, so you'll see a +2 on the day_of_week field.
This give me:
Now back to my weekly assessment.
Also, we calculate our weeks as Monday - Sunday, so you'll see a +2 on the day_of_week field.
SELECT StartDt , EXTRACT(DAY from StartDt) as DayOfMonth , day_of_week + 2 as DayOfWeek , StartDt - (day_of_week + 2) as FirstDayOfWeek from mydb.table INNER JOIN sys_calendar.calendar ON StartDt = calendar_date;
This give me:
SubStartDt DayOfMonth DayOfWeek FirstDayOfWeek 09/25/2009 25 8 09/21/2009 10/12/2009 12 4 10/12/2009 09/28/2009 28 4 09/28/2009 10/17/2009 17 9 10/12/2009 09/29/2009 29 5 09/28/2009 10/15/2009 15 7 10/12/2009 10/07/2009 7 6 10/05/2009 10/16/2009 16 8 10/12/2009 10/11/2009 11 3 10/12/2009 10/04/2009 4 3 10/05/2009
Now back to my weekly assessment.
Monday, October 26, 2009
Renaming a Column in Teradata
Sometimes it's the little stuff where syntax differences between DMBSs get me. Today I had to look up how to rename a column. Easy enough stuff:
ALTER TABLE mydb.foo RENAME OldColumnName TO NewColumnName;
ALTER TABLE mydb.foo RENAME OldColumnName TO NewColumnName;
Monday, October 19, 2009
Teradata Date Conversion - Getting the First day of the Month
I have a table containing start dates and I want to identify all the records for a given month by their month. This will allow me to identify sets of users by their signup month.
Thanks to a tip from Craig F. I can do this by subtracting from the date the day of the month minus 1. This will ensure that regardless of the date I choose, all my dates are returned as the first of the month.
I created a table (foo) with one column (startdt type DATE) and three records:
select * from foo
== Results ==
startdt
12/31/2009 12:00:00 AM
8/1/2009 12:00:00 AM
7/15/2009 12:00:00 AMNow I want to get the number of days to subtract from the day in the date. To do this, I use Teradata’s EXTRACT function and get the day of the date:
EXTRACT(Day from StartDt) as DayOfDate
and I get the number day value : 31, 1, 15
EXTRACT(Month from StartDt) returns the month values 12, 8, 7
EXTRACT(Year from StartDt) returns 2009
Now that I have the numeric day of the month I simply subtract one from it:
SELECT startdt
, startdt - INTERVAL '1' DAY as Start_Minus_1_Day
, EXTRACT(Day from StartDt) -1 as DaySubAmount
, startdt - (EXTRACT(DAY from StartDt) -1) as FirstofMonth
FROM database.foo
You'll notice another function you can do with dates is add or subtract an
INTERVAL. There is a lot you can do with INTERVAL so I'll limit my comments here to how I used it.Above I subtracted 1 day from the date using
- INTERVAL '1' DAY. Day could be replaced with Month, Year, Hour, Minute, Second and transformations (like Day to Second). You can also Add an INTERVAL to a date using the same syntax.My final result set was:
startddt Start_Minus_1_Day DaySubAmount FirstofMonth 8/1/2009 0:00 7/31/2009 0:00 0 8/1/2009 0:00 7/15/2009 0:00 7/14/2009 0:00 14 7/1/2009 0:00 12/31/2009 0:00 12/30/2009 0:00 30 12/1/2009 0:00
Subscribe to:
Posts (Atom)