We have a table called "subscriptions" that stores information about salon subscriptions. The table has the following columns:
subscriptions
id, start_date, end_date, subscription_plan_id, salon_id
We want to write a query that provides the following information for each month:
-
Date
-
Total number of subscriptions (Running Total)
-
Number of new subscriptions
-
Number of lost subscriptions
-
Total number of subscriptions for each subscription plan (standard, grow, basic, and free)
-
Number of new subscriptions for each subscription plan (standard, grow, basic, and free)
-
Number of lost subscriptions for each subscription plan (standard, grow, basic, and free)
The total
values should represent the cumulative count overall, excluding lost subscriptions for each month. The new
and lost
values should be specific to each month.
I got the result I wanted but using the queries below
SELECT Date.date,
COUNT(CASE WHEN Date.date BETWEEN DATE_FORMAT(s.start_date, '%Y-%m') AND DATE_FORMAT(s.end_date, '%Y-%m')
THEN s.salon_id
END) AS total_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(s.start_date, '%Y-%m')
THEN s.salon_id
END) AS new_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(DATE_ADD(s.end_date, INTERVAL 1 MONTH), '%Y-%m')
THEN s.salon_id
END) AS lost_subs,
COUNT(CASE WHEN Date.date BETWEEN DATE_FORMAT(s.start_date, '%Y-%m') AND DATE_FORMAT(s.end_date, '%Y-%m')
AND s.subscription_plan_id = 4
THEN s.salon_id
END) AS total_standard_subs,
COUNT(CASE WHEN Date.date BETWEEN DATE_FORMAT(s.start_date, '%Y-%m') AND DATE_FORMAT(s.end_date, '%Y-%m')
AND s.subscription_plan_id = 3
THEN s.salon_id
END) AS total_grow_subs,
COUNT(CASE WHEN Date.date BETWEEN DATE_FORMAT(s.start_date, '%Y-%m') AND DATE_FORMAT(s.end_date, '%Y-%m')
AND s.subscription_plan_id = 2
THEN s.salon_id
END) AS total_basic_subs,
COUNT(CASE WHEN Date.date BETWEEN DATE_FORMAT(s.start_date, '%Y-%m') AND DATE_FORMAT(s.end_date, '%Y-%m')
AND s.subscription_plan_id = 1
THEN s.salon_id
END) AS total_free_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(s.start_date, '%Y-%m')
AND s.subscription_plan_id = 4
THEN s.salon_id
END) AS new_standard_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(s.start_date, '%Y-%m')
AND s.subscription_plan_id = 3
THEN s.salon_id
END) AS new_grow_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(s.start_date, '%Y-%m')
AND s.subscription_plan_id = 2
THEN s.salon_id
END) AS new_basic_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(s.start_date, '%Y-%m')
AND s.subscription_plan_id = 1
THEN s.salon_id
END) AS new_free_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(DATE_ADD(s.end_date, INTERVAL 1 MONTH), '%Y-%m')
AND s.subscription_plan_id = 4
THEN s.salon_id
END) AS lost_standard_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(DATE_ADD(s.end_date, INTERVAL 1 MONTH), '%Y-%m')
AND s.subscription_plan_id = 3
THEN s.salon_id
END) AS lost_grow_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(DATE_ADD(s.end_date, INTERVAL 1 MONTH), '%Y-%m')
AND s.subscription_plan_id = 2
THEN s.salon_id
END) AS lost_basic_subs,
COUNT(CASE WHEN Date.date = DATE_FORMAT(DATE_ADD(s.end_date, INTERVAL 1 MONTH), '%Y-%m')
AND s.subscription_plan_id = 1
THEN s.salon_id
END) AS lost_free_subs
FROM(
SELECT CONCAT(YEAR(start_date),'-', LPAD(MONTH(start_date), 2, '0')) AS date FROM subscriptions
UNION
SELECT CONCAT(YEAR(start_date),'-', LPAD(MONTH(start_date), 2, '0')) AS date FROM subscriptions
) AS Date
CROSS JOIN subscriptions AS s
WHERE Date.date <= DATE_FORMAT(CURDATE(), '%Y-%m')
GROUP BY Date. date
ORDER BY Date.date DESC;
I am looking for a more efficient and streamlined approach to achieve the same result.
Thanks For Help In Advance!
2
Answers
This is the best possible we were able to achieve thanks to @lemons help
I am accepting this as a answer if we get any better answer in future i'll update it!
You could try following these steps:
INNER JOIN
with aCROSS JOIN
CASE
expression