George D.
George D.

Reputation: 1650

Mysql sum for last 12 months

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 :-)

enter image description here

Upvotes: 0

Views: 1448

Answers (3)

Richard
Richard

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

Jaugar Chang
Jaugar Chang

Reputation: 3196

Replace ORDER BY data.Montha to ORDER BY Months.MONTH

There is no '3/14' in data.Montha.

Upvotes: 0

user934801
user934801

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

Related Questions