__STYLES__
In this project, I acted as a Business Intelligence Consultant for Maven Communications, a California-based Telecommunications company.
My primary goal was to help the company improve retention by identifying high value customers and churn risks.
Look into why customers from San Diego are leaving at a higher rate. Internet type may play a role as most of the customers leaving utilized fiber optics.
Assess the competition; most churned customers stated that they were leaving due to better devices or better offers from competitors.
Consider trialing special offers for customers who choose a one- or two-year contract. Of churned customers, 1655 of them (89%) were on month-to-month contracts.
Consider incentivizing referrals. The majority of customers (54%) have not given any referrals. Within churned customers, 507 had done one referral, while 579 of current customers had also done one referral. Were churned customers expecting something that they didn’t get and then choose to not refer more?
This dataset contains 2 tables, in CSV format:
source: Maven Churn Challenge
7043
5174
73.46%
SET @totalqty := (
SELECT
COUNT(customer_status)
FROM telecom_customer_churn
WHERE customer_status IN ('joined', 'stayed', 'churned'));
SELECT
customer_status
, COUNT(customer_status) AS churn_counted
, ROUND((COUNT(customer_status))/@totalqty * 100, 2) AS percent
FROM telecom_customer_churn
WHERE customer_status = 'churned'
GROUP BY customer_status;
SELECT
'Current_Cust' AS Type
, COUNT(CASE WHEN age BETWEEN 19 AND 24 THEN 1 END) AS early20s
, COUNT(CASE WHEN age BETWEEN 25 AND 29 THEN 1 END) AS late20s
, COUNT(CASE WHEN age BETWEEN 30 AND 34 THEN 1 END) AS early30s
, COUNT(CASE WHEN age BETWEEN 35 AND 39 THEN 1 END) AS late30s
, COUNT(CASE WHEN age BETWEEN 40 AND 44 THEN 1 END) AS early40s
, COUNT(CASE WHEN age BETWEEN 45 AND 49 THEN 1 END) AS late40s
, COUNT(CASE WHEN age BETWEEN 50 AND 54 THEN 1 END) AS early50s
, COUNT(CASE WHEN age BETWEEN 55 AND 59 THEN 1 END) AS late50s
, COUNT(CASE WHEN age BETWEEN 60 AND 64 THEN 1 END) AS early60s
, COUNT(CASE WHEN age BETWEEN 65 AND 69 THEN 1 END) AS late60s
, COUNT(CASE WHEN age BETWEEN 70 AND 74 THEN 1 END) AS early70s
, COUNT(CASE WHEN age > 74 THEN 1 END) AS late70s
FROM telecom_customer_churn
WHERE customer_status IN ('stayed', 'joined')
UNION ALL
SELECT
'Total_Cust'
, COUNT(CASE WHEN age BETWEEN 19 AND 24 THEN 1 END) AS early20s
, COUNT(CASE WHEN age BETWEEN 25 AND 29 THEN 1 END) AS late20s
, COUNT(CASE WHEN age BETWEEN 30 AND 34 THEN 1 END) AS early30s
, COUNT(CASE WHEN age BETWEEN 35 AND 39 THEN 1 END) AS late30s
, COUNT(CASE WHEN age BETWEEN 40 AND 44 THEN 1 END) AS early40s
, COUNT(CASE WHEN age BETWEEN 45 AND 49 THEN 1 END) AS late40s
, COUNT(CASE WHEN age BETWEEN 50 AND 54 THEN 1 END) AS early50s
, COUNT(CASE WHEN age BETWEEN 55 AND 59 THEN 1 END) AS late50s
, COUNT(CASE WHEN age BETWEEN 60 AND 64 THEN 1 END) AS early60s
, COUNT(CASE WHEN age BETWEEN 65 AND 69 THEN 1 END) AS late60s
, COUNT(CASE WHEN age BETWEEN 70 AND 74 THEN 1 END) AS early70s
, COUNT(CASE WHEN age > 74 THEN 1 END) AS late70s
FROM telecom_customer_churn;
Type | Early 20s | Late 20s | Early 30s | Late 30s | Early 40s | Late 40s | Early 50s | Late 50s | Early 60s | Late 60s | Early 70s | Late 70s |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Current Customers | 621 | 476 | 470 | 487 | 511 | 513 | 461 | 484 | 485 | 212 | 211 | 243 |
Total Customers | 779 | 622 | 626 | 640 | 677 | 665 | 621 | 631 | 640 | 364 | 358 | 420 |
SET @totalqty := (
SELECT
COUNT(churn_cat)
FROM telecom_customer_churn
WHERE churn_cat IN ('attitude', 'price', 'dissatisfaction', 'competitor', 'other'));
SELECT
churn_cat
, COUNT(churn_cat) AS number_per_category
, ROUND((COUNT(churn_cat))/@totalqty * 100, 2) AS percent
FROM telecom_customer_churn
WHERE churn_cat IN ('attitude', 'price', 'dissatisfaction', 'competitor', 'other')
GROUP BY churn_cat;
Churn Category | Number/Category | Percent |
---|---|---|
Competitor | 841 | 45% |
Dissatisfaction | 321 | 17.17% |
Other | 182 | 9.74% |
Price | 211 | 11.29% |
Attitude | 314 | 16.8% |
SELECT
CASE
WHEN tenure_months <= 12 THEN 'first year'
WHEN tenure_months BETWEEN 13 AND 24 THEN 'second year'
WHEN tenure_months BETWEEN 25 AND 36 THEN 'third year'
WHEN tenure_months BETWEEN 37 AND 48 THEN 'fourth year'
WHEN tenure_months BETWEEN 49 AND 60 THEN 'fifth year'
ELSE 'more than 5 years'
END AS monthly_tenure,
COUNT(*) AS number_of_customers
FROM telecom_customer_churn
WHERE customer_status IN ('stayed', 'joined')
GROUP BY monthly_tenure
ORDER BY number_of_customers DESC;
As noted in the exploratory analysis, 26.54% of customers in the database have churned. The majority of customers were in the San Diego area, as over half of the San Diego customer base churned (185 out of 285). The most frequent reason customers gave for churning was “competitor” at 45% with “dissatisfaction” (17.17%) and “attitude” (16.8%) coming in 2nd and 3rd, respectively. To determine in more detail why customers might churn, I analyzed the following:
`SELECT
'Past_Cust' AS Type
, COUNT(CASE WHEN age BETWEEN 19 AND 24 THEN 1 END) AS early20s
, COUNT(CASE WHEN age BETWEEN 25 AND 29 THEN 1 END) AS late20s
, COUNT(CASE WHEN age BETWEEN 30 AND 34 THEN 1 END) AS early30s
, COUNT(CASE WHEN age BETWEEN 35 AND 39 THEN 1 END) AS late30s
, COUNT(CASE WHEN age BETWEEN 40 AND 44 THEN 1 END) AS early40s
, COUNT(CASE WHEN age BETWEEN 45 AND 49 THEN 1 END) AS late40s
, COUNT(CASE WHEN age BETWEEN 50 AND 54 THEN 1 END) AS early50s
, COUNT(CASE WHEN age BETWEEN 55 AND 59 THEN 1 END) AS late50s
, COUNT(CASE WHEN age BETWEEN 60 AND 64 THEN 1 END) AS early60s
, COUNT(CASE WHEN age BETWEEN 65 AND 69 THEN 1 END) AS late60s
, COUNT(CASE WHEN age BETWEEN 70 AND 74 THEN 1 END) AS early70s
, COUNT(CASE WHEN age > 74 THEN 1 END) AS late70s
FROM telecom_customer_churn
WHERE customer_status IN ('churned')
UNION ALL
SELECT
'Total_Cust'
, COUNT(CASE WHEN age BETWEEN 19 AND 24 THEN 1 END) AS early20s
, COUNT(CASE WHEN age BETWEEN 25 AND 29 THEN 1 END) AS late20s
, COUNT(CASE WHEN age BETWEEN 30 AND 34 THEN 1 END) AS early30s
, COUNT(CASE WHEN age BETWEEN 35 AND 39 THEN 1 END) AS late30s
, COUNT(CASE WHEN age BETWEEN 40 AND 44 THEN 1 END) AS early40s
, COUNT(CASE WHEN age BETWEEN 45 AND 49 THEN 1 END) AS late40s
, COUNT(CASE WHEN age BETWEEN 50 AND 54 THEN 1 END) AS early50s
, COUNT(CASE WHEN age BETWEEN 55 AND 59 THEN 1 END) AS late50s
, COUNT(CASE WHEN age BETWEEN 60 AND 64 THEN 1 END) AS early60s
, COUNT(CASE WHEN age BETWEEN 65 AND 69 THEN 1 END) AS late60s
, COUNT(CASE WHEN age BETWEEN 70 AND 74 THEN 1 END) AS early70s
, COUNT(CASE WHEN age > 74 THEN 1 END) AS late70s
FROM telecom_customer_churn;
Type | Early 20s | Late 20s | Early 30s | Late 30s | Early 40s | Late 40s | Early 50s | Late 50s | Early 60s | Late 60s | Early 70s | Late 70s |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Churned | 158 | 146 | 156 | 153 | 166 | 152 | 160 | 147 | 155 | 152 | 147 | 177 |
Total | 779 | 622 | 626 | 640 | 677 | 665 | 621 | 631 | 640 | 364 | 358 | 420 |
Percentage | 20.28% | 23.47% | 24.92% | 23.91% | 24.52% | 22.86% | 25.76% | 23.3% | 24.22% | 41.76% | 41.06% | 42.14% |
Number of dependents | Number of churned customers |
---|---|
0 | 1763 |
1 | 38 |
2 | 33 |
3 | 30 |
4 | 1 |
5 | 2 |
6 | 1 |
7 | 1 |
Customer Status | Offer A | Offer B | Offer C | Offer D | Offer E | None |
---|---|---|---|---|---|---|
Stayed | 485 | 723 | 320 | 441 | 204 | 2547 |
Churned | 35 | 101 | 95 | 161 | 426 | 1051 |
Joined | 0 | 0 | 0 | 0 | 175 | 279 |
`SELECT
churn_cat,
COUNT(*) AS number_customers
FROM telecom_customer_churn
WHERE offer = 'offer E'
GROUP BY churn_cat
ORDER BY churn_cat DESC;
SELECT
churn_reason,
COUNT(churn_reason) AS reason
FROM telecom_customer_churn
WHERE customer_status = 'churned' and offer = 'offer e'
GROUP BY churn_reason
ORDER BY reason DESC
LIMIT 10;
WITH churned_customers AS (SELECT * FROM telecom_customer_churn
WHERE customer_status = 'churned')
SELECT
'minimum' AS Type,
MIN(total_revenue) AS total_revenue,
MIN(total_charges) AS quarterly,
MIN(monthly_charge) AS monthly
FROM churned_customers
UNION ALL
SELECT
'maximum',
MAX(total_revenue) AS total_revenue,
MAX(total_charges) AS quarterly,
MAX(monthly_charge) AS monthly
FROM churned_customers
UNION ALL
SELECT
'average',
ROUND(AVG(total_revenue),2) AS total_revenue,
ROUND(AVG(total_charges),2) AS quarterly,
ROUND(AVG(monthly_charge),2) AS monthly
FROM churned_customers;
Type | Total Revenue | Quarterly | Monthly |
---|---|---|---|
Minimum | 26.61 | 18.85 | -10 |
Maximum | 11195.44 | 8684.8 | 118.35 |
Average | 1971.35 | 1531.8 | 73.35 |
SET @totalchurned := (SELECT COUNT(churn_reason) FROM telecom_customer_churn WHERE customer_status = 'churned');
SELECT
churn_reason,
COUNT(churn_reason) AS num_per_reason,
ROUND(COUNT(churn_reason) * 100 / @totalchurned,2) AS percent_per_reason
FROM telecom_customer_churn
WHERE customer_status = 'churned'
GROUP BY churn_reason
ORDER BY num_per_reason DESC
LIMIT 5;
Churn reason | Number/reason | Percent/reason |
---|---|---|
Competitor: better devices | 313 | 16.75% |
Competitor: better offer | 311 | 16.64% |
Attitude: support person | 220 | 11.77% |
Don't know | 130 | 6.96% |
Competitor: more data | 117 | 6.26% |
Before beginning my analysis, I qualified metrics on what qualities we would measure “high value” by. A high value customer is one whose business will significantly impact the bottom line. Total revenue, usage of multiple services, average revenue per account (APRA), tenure, and number of referrals are all ways we could gain insight into high level customers.
`WITH cte AS (
SELECT
customerID
, total_revenue
, customer_status
FROM (
SELECT
telecom_customer_churn.*
, @counter := @counter +1 AS counter
FROM (select @counter:=0) AS initvar,
telecom_customer_churn
ORDER BY total_revenue DESC
) AS X
WHERE counter <= (33/100 * @counter)
ORDER BY total_revenue DESC)`
SELECT
COUNT(customerID) AS num_churned
, ROUND(COUNT(customerID) * 100 / (SELECT COUNT(*) FROM cte),2) AS percent_churned
, ROUND(SUM(total_revenue)) AS revenue_lost
FROM cte
WHERE customer_status = 'churned';
SET @arpa := (
SELECT
ROUND(SUM(total_revenue) / COUNT(customerID),2) AS ARPA
FROM telecom_customer_churn);
SELECT
COUNT(customerID) AS num_cust
, ROUND(AVG(total_revenue),2) AS avg_total_rev
, ROUND(AVG(total_revenue) * 100 / @arpa) AS percent_of_arpa
FROM telecom_customer_churn
WHERE total_revenue > @arpa AND customer_status ='churned';