Turns out there were two ways - Stored Procedure, which takes too much memory, or using CASE WHEN, this pivots the table as well. Hope it's useful to people who have to generate reports showing various activity per user day by day or month by month on the x axis. The main difficulty I had was the fact that Month_1 (first purchased subscription) was a different date for every user. This report can be used to analyse your users behavior in the first 6 months of their subscription.
The report generated by this query looks like this:
+--------+----------+------------------+---------+---------+--------+
| UserId | Currency | FirstSubscrPurch | Month_1 | Month_2 | etc... |
+--------+----------+------------------+---------+---------+--------+
| 123 | GBP | 2010-05-27 | 34.00 | 27.00 | 0.00 |
+--------+----------+------------------+---------+---------+--------+
SELECT F6.USERID, F6.Currency, DATE_FORMAT(F6.FirstSubscrPurch, "%Y-%m-%d") AS FirstSubscrPurch, F6.MONTH_1, F6.MONTH_2,F6.MONTH_3, F6.MONTH_4, F6.MONTH_5, F6.MONTH_6, ROUND(((F6.MONTH_1+F6.MONTH_2+F6.MONTH_3+F6.MONTH_4+F6.MONTH_5+F6.MONTH_6)/6),2) AVERAGE, F6.CURRENCY
FROM (
SELECT
UserId, Currency, FirstSubscrPurch,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 0 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_1,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 1 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_2,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 2 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_3,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 3 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_4,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 4 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_5,
SUM(CASE WHEN YEAR_AND_MONTH_INDEX = 5 THEN TOTAL_AMOUNT_PAID ELSE 0 END) MONTH_6
FROM (
SELECT
hp.UserId, hp.Currency, MIN(hp.Date) AS FirstSubscrPurch,
CONCAT(YEAR(Date),'-',MONTH(Date)) AS YEAR_AND_MONTH,
TIMESTAMPDIFF( MONTH, CONCAT(YEAR(FIRST_PAYMENT_DATE),'-',MONTH(FIRST_PAYMENT_DATE),'-1'), CONCAT(YEAR(Date),'-',MONTH(Date),'-1')) AS YEAR_AND_MONTH_INDEX, -- generates string in format YYYY-M-D
MIN(Date) FIRST_PAYMENT_OF_MONTH,
MAX(Date) LAST_PAYMENT_OF_MONTH,
COUNT(*) NUM_PAYMENTS,
SUM(hp.Amount) TOTAL_AMOUNT_PAID,
SUM(hp.Credits) Credits
FROM payments hp
JOIN (
SELECT UserId, MIN(Date) FIRST_PAYMENT_DATE, ADDDATE(MIN(Date), INTERVAL 6 MONTH) SIX_MONTHS_AFTER_FIRST_PAYMENT
FROM payments hp
GROUP BY UserId
) USER_MIN_ID ON USER_MIN_ID.UserId = hp.UserId
AND hp.Date BETWEEN FIRST_PAYMENT_DATE AND CONCAT(YEAR(SIX_MONTHS_AFTER_FIRST_PAYMENT),'-',MONTH(SIX_MONTHS_AFTER_FIRST_PAYMENT),'-1')
GROUP BY UserId, Currency, YEAR_AND_MONTH
ORDER BY hp.UserId, hp.Date
) F
GROUP BY UserId, Currency
ORDER BY UserId DESC) F6;