I have a Users table (id, name, created_at) and a Transaction table(id, user_id, created_at, amount).
For each month, I would like to know the number of users who did not have any transaction in the 3 months interval before that month.
For example, for April 2022, the query would return number of users who did not have a transaction in January 2022, February 2022 and March 2022. And so on for every month.
Can I do this with a single MySQL query, and without PHP loop?
If I wanted it for April 2022 only, then I guess this would do the trick:
SELECT count(distinct(users.id)) FROM users
INNER JOIN transactions
on users.id = transactions.user_id
WHERE transactions.user_id NOT IN
(SELECT user_id FROM transactions WHERE created_at > "2022-01-01" AND created_at < "2022-04-01" );
How to get it for all months?
2
Answers
In a normal situation, you would have a calendar table that, for examples, stores all starts of months over a wide period of time, like
calendar(start_of_month)
.From there on, you can
cross join
the calendar with the users table to generate all possible combinations of months and customers (with respect to the user’s creation time). The last step is to check each user/month tuple for transations in the last 3 months.This gives you one row per month that has at least one "inactive" customers,with the corresponding count.
You control the range of months over which the query applies with the
where
clause to the query (as an example, the above gives you all year 2021).