Reputation: 1650
I am trying to create a query to get the last 12 month records based on month for chart representation. After a lot of reading and after watching this similar topic I created a query that seems right but missing the months with 0 money. As an example, I see in my graph months 1/14,2/14,4/14 and so on... 3/14 is missing.
My code is this
SELECT *
FROM
(SELECT DATE_FORMAT(now(), '%m/%y') AS Month
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 1 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 2 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 3 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 4 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 5 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 6 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 7 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 8 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 9 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 10 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 11 MONTH), '%m/%y')
) AS Months
LEFT JOIN
(SELECT sum(expenses.price) AS ExpenseAmount,
sum(payments.amount) AS PaymentsAmount,
DATE_FORMAT(expenses.date_occurred,'%m/%y') AS Month,
DATE_FORMAT(payments.date_occurred,'%m/%y') AS Montha
FROM expenses,
payments
WHERE payments.user_id= 1
AND payments.user_id=expenses.user_id
GROUP BY MONTH(payments.date_occurred),
YEAR(payments.date_occurred)
ORDER BY payments.date_occurred ASC ) data ON Months.MONTH = data.Montha
ORDER BY data.Montha;
Any help will be great as this kind of queries are too advanced for me :-)
Upvotes: 0
Views: 1448
Reputation: 30618
As the query looks like it should produce a row for each month, can you check the query output, rather than what your graph is producing? I suspect you've got an entry for 04/14, but that the value is NULL rather than 0. To correct this, you can change the query to start
SELECT Months.Month,
COALESCE(data.ExpenseAmount, 0) AS ExpenseAmount,
COALESCE(data.PaymentAmount, 0) AS PaymentAmount
COALESCE will give you 0 instead of NULL where there are no rows matching your left join.
However, there are further problems in your query. You will only get rows if there is an expense and a payment in the same month - check http://sqlfiddle.com/#!2/3f52a8/1 and you'll see the problem if you remove some of the data from one table.
Here's a working solution which will give you all months, summing the data from both tables, even if only one is present. This works by handling the expenses and payments as separate queries, then joining them together.
SELECT Months.Month, COALESCE(expensedata.ExpenseAmount, 0) AS ExpenseAmount, COALESCE(paymentdata.PaymentAmount, 0) AS PaymentAmount
FROM
(SELECT DATE_FORMAT(now(), '%m/%y') AS Month
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 1 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 2 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 3 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 4 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 5 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 6 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 7 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 8 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 9 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 10 MONTH), '%m/%y')
UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 11 MONTH), '%m/%y')
) AS Months
LEFT JOIN
(SELECT SUM(price) AS ExpenseAmount, DATE_FORMAT(date_occurred,'%m/%y') AS Month
FROM expenses
WHERE user_id = 1
GROUP BY MONTH(date_occurred), YEAR(date_occurred)) expensedata ON Months.Month = expensedata.Month
LEFT JOIN
(SELECT SUM(amount) AS PaymentAmount, DATE_FORMAT(date_occurred,'%m/%y') AS Month
FROM payments
WHERE user_id = 1
GROUP BY MONTH(date_occurred), YEAR(date_occurred)) paymentdata ON Months.Month = paymentdata.Month
ORDER BY Months.Month;
SQL Fiddle showing this working: http://sqlfiddle.com/#!2/3f52a8/5
Upvotes: 1
Reputation: 3196
Replace ORDER BY data.Montha
to ORDER BY Months.MONTH
There is no '3/14' in data.Montha.
Upvotes: 0
Reputation: 1139
i think your problem is the left join. the result of the select statement inside your left join does not contain any results with 0 money ... it looks like your
where payments.user_id = 1
is the matter...
under the following link you can find an explanation to all types of joins... http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
hope that helps
Upvotes: 0