Repository navigation
Expand file tree
/
Copy pathDay10 Script.sql
More file actions
193 lines (186 loc) · 7.66 KB
/
Copy pathDay10 Script.sql
File metadata and controls
193 lines (186 loc) · 7.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
-- Build RFM Metrics for Every Customer
SELECT c.customer_name, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name
ORDER BY recency, frequency DESC, monetary DESC;
-- Create RFM Scores (1–5)
WITH cte1 AS (
SELECT c.customer_name, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name
ORDER BY recency, frequency DESC, monetary DESC
) SELECT customer_name, recency,
NTILE(5) OVER(ORDER BY recency ASC) AS recency_score,
frequency, NTILE(5) OVER(ORDER BY frequency DESC) AS frequency_score,
monetary, NTILE(5) OVER(ORDER BY monetary DESC) AS monetary_score,
(NTILE(5) OVER(ORDER BY recency DESC) + NTILE(5) OVER(ORDER BY frequency ASC) + NTILE(5) OVER(ORDER BY monetary ASC)) AS rfm_score
FROM cte1
ORDER BY rfm_score DESC;
-- Create Customer Segments Using RFM
WITH cte1 AS (
SELECT c.customer_name, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name
ORDER BY recency, frequency DESC, monetary DESC
), cte2 AS (
SELECT customer_name, recency,
NTILE(5) OVER(ORDER BY recency ASC) AS recency_score,
frequency, NTILE(5) OVER(ORDER BY frequency DESC) AS frequency_score,
monetary, NTILE(5) OVER(ORDER BY monetary DESC) AS monetary_score,
(NTILE(5) OVER(ORDER BY recency DESC) + NTILE(5) OVER(ORDER BY frequency ASC) + NTILE(5) OVER(ORDER BY monetary ASC)) AS rfm_score
FROM cte1
ORDER BY rfm_score DESC
) SELECT customer_name, rfm_score,
CASE WHEN recency_score >= 4 AND frequency_score >= 4 AND monetary_score >=4 THEN "Champion"
WHEN recency_score >= 3 AND frequency_score >= 3 THEN "Loyal Customer"
WHEN recency_score = 5 AND frequency_score <= 2 THEN "New Customer"
WHEN recency_score <= 2 AND frequency_score >= 4 THEN "At Risk"
WHEN recency_score <= 2 AND frequency_score <= 4 THEN "Lost Customer"
ELSE "Potential Loyalists" END AS segement
FROM cte2;
-- Revenue Contribution by Customer Segment
WITH cte1 AS (
SELECT c.customer_name, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name
ORDER BY recency, frequency DESC, monetary DESC
), cte2 AS (
SELECT customer_name, recency,
NTILE(5) OVER(ORDER BY recency ASC) AS recency_score,
frequency, NTILE(5) OVER(ORDER BY frequency DESC) AS frequency_score,
monetary, NTILE(5) OVER(ORDER BY monetary DESC) AS monetary_score,
(NTILE(5) OVER(ORDER BY recency DESC) + NTILE(5) OVER(ORDER BY frequency ASC) + NTILE(5) OVER(ORDER BY monetary ASC)) AS rfm_score
FROM cte1
ORDER BY rfm_score DESC
),cte3 AS (
SELECT customer_name, monetary,
CASE WHEN recency_score >= 4 AND frequency_score >= 4 AND monetary_score >=4 THEN "Champion"
WHEN recency_score >= 3 AND frequency_score >= 3 THEN "Loyal Customer"
WHEN recency_score = 5 AND frequency_score <= 2 THEN "New Customer"
WHEN recency_score <= 2 AND frequency_score >= 4 THEN "At Risk"
WHEN recency_score <= 2 AND frequency_score <= 4 THEN "Lost Customer"
ELSE "Potential Loyalists" END AS segement
FROM cte2
) SELECT segement,
COUNT(customer_name) AS total_customer,
ROUND(SUM(monetary),2) AS total_revenue,
ROUND(AVG(monetary),2) AS avg_revenue_per_customer,
ROUND((SUM(monetary) / SUM(SUM(monetary)) OVER()) * 100,2) AS revenue_contri_pct
FROM cte3
GROUP BY segement
ORDER BY total_revenue DESC;
-- Identify High-Value Customers at Risk
WITH cte1 AS (
SELECT c.customer_name, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency, MAX(o.order_date) AS last_order_date,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name
ORDER BY recency, frequency DESC, monetary DESC
),cte2 AS (SELECT customer_name, recency, last_order_date,
NTILE(5) OVER(ORDER BY recency ASC) AS recency_score,
frequency, NTILE(5) OVER(ORDER BY frequency DESC) AS frequency_score,
monetary, NTILE(5) OVER(ORDER BY monetary DESC) AS monetary_score,
(NTILE(5) OVER(ORDER BY recency DESC) + NTILE(5) OVER(ORDER BY frequency ASC) + NTILE(5) OVER(ORDER BY monetary ASC)) AS rfm_score
FROM cte1
ORDER BY rfm_score DESC
) SELECT customer_name,
monetary AS revenue,
DATE(last_order_date) AS last_order_date,
recency as days_since_last_order
FROM cte2
WHERE monetary_score >=4
AND frequency_score >=4
AND recency_score <=2;
-- Customer Lifetime Value Segmentation
WITH cte1 AS(
SELECT customer_id, SUM(net_amount) AS CLV
FROM orders
WHERE order_status = "Delivered"
GROUP BY customer_id
), cte2 AS(
SELECT customer_id, CLV,
CASE WHEN CLV >= 30000 THEN "VIP"
WHEN CLV >= 15000 AND CLV <= 29999 THEN "High_value"
WHEN CLV >= 5000 AND CLV <= 14999 THEN "Medium_value"
ELSE "Low_value" END AS segement
FROM cte1
) SELECT segement,
COUNT(customer_id) AS total_customer,
SUM(CLV) AS total_revenue,
ROUND(SUM(CLV) / COUNT(customer_id),2) AS avg_revenue
FROM cte2
GROUP BY segement;
-- City-wise RFM Performance
WITH cte1 AS (
SELECT c.customer_name, o.city_id, DATEDIFF(CURDATE(),MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency, SUM(o.net_amount) as monetary
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_name, o.city_id
ORDER BY recency, frequency DESC, monetary DESC
) SELECT c.city_name, ROUND(AVG(recency),2) AS avg_recency,
ROUND(AVG(frequency),2) AS avg_frequency,
ROUND(AVG(monetary),2) AS avg_monetary,
DENSE_RANK() OVER(ORDER BY AVG(monetary) DESC) AS monetary_rank
FROM cte1
JOIN cities AS c
ON cte1.city_id = c.city_id
GROUP BY c.city_name;
-- Executive Customer Dashboard
WITH cte1 AS (
SELECT c.customer_id,c.customer_name,
DATEDIFF(CURDATE(), MAX(o.order_date)) AS recency,
COUNT(o.order_id) AS frequency,
SUM(o.net_amount) AS monetary -- Changed net_amount to amount based on schema
FROM orders AS o
JOIN customers AS c ON o.customer_id = c.customer_id
WHERE o.order_status = "Delivered"
GROUP BY c.customer_id, c.customer_name
),cte2 AS (
SELECT customer_name, monetary,
NTILE(5) OVER(ORDER BY recency ASC) AS recency_score,
NTILE(5) OVER(ORDER BY frequency DESC) AS frequency_score,
NTILE(5) OVER(ORDER BY monetary DESC) AS monetary_score
FROM cte1
),cte3 AS (
SELECT customer_name, monetary,
CASE WHEN recency_score >= 4 AND frequency_score >= 4 AND monetary_score >= 4 THEN 'Champion'
WHEN recency_score >= 3 AND frequency_score >= 3 THEN 'Loyal Customer'
WHEN recency_score = 5 AND frequency_score <= 2 THEN 'New Customer'
WHEN recency_score <= 2 AND frequency_score >= 4 THEN 'At Risk'
WHEN recency_score <= 2 AND frequency_score <= 4 THEN 'Lost Customer'
ELSE 'Potential Loyalists'
END AS segment
FROM cte2
)SELECT
COUNT(customer_name) AS total_customers,
COUNT(CASE WHEN segment = 'Champion' THEN 1 END) AS champions,
COUNT(CASE WHEN segment = 'Loyal Customer' THEN 1 END) AS loyal_customers,
COUNT(CASE WHEN segment = 'At Risk' THEN 1 END) AS at_risk_customers,
COUNT(CASE WHEN segment = 'Lost Customer' THEN 1 END) AS lost_customers,
ROUND(SUM(monetary), 2) AS total_revenue,
ROUND(SUM(CASE WHEN segment = 'Champion' THEN monetary ELSE 0 END), 2) AS revenue_from_champions,
ROUND((SUM(CASE WHEN segment = 'Champion' THEN monetary ELSE 0 END) / NULLIF(SUM(monetary), 0)) * 100, 2) AS champion_revenue_pct,
ROUND(AVG(monetary), 2) AS average_customer_revenue
FROM cte3;