Frage

I need to generate a report 12 months before the current date.

Today is 2014-04-29. So my date range would be 2013-04-29 to 2014-04-29.

These is my sample data:

--------------------------------------
-- user_id | lead_id | date_entered --
--       1 |       1 | 2013-12-05   --
--       1 |       2 | 2014-03-15   --
--       1 |       3 | 2014-04-24   --
--------------------------------------

Expected output should be:

--------------------------
-- month | year | total --
--   Apr | 2013 |     0 --
--   May | 2013 |     0 --
--   Jun | 2013 |     0 --
--   Jul | 2013 |     0 --
--   Aug | 2013 |     0 --
--   Sep | 2013 |     0 --
--   Oct | 2013 |     0 --
--   Nov | 2013 |     0 --
--   Dec | 2013 |     1 --
--   Jan | 2014 |     0 --
--   Feb | 2014 |     0 --
--   Mar | 2014 |     1 --
--   Apr | 2014 |     1 --
--------------------------

Here is my query:

select a.month, a.year, IFNULL(d.total, 0) AS total
from (
    SELECT 'Apr' month, 2013 year, 1 monthOrder UNION 
    SELECT 'May' month, 2013 year, 2 monthOrder UNION 
    SELECT 'Jun' month, 2013 year, 3 monthOrder UNION 
    SELECT 'Jul' month, 2013 year, 4 monthOrder UNION 
    SELECT 'Aug' month, 2013 year, 5 monthOrder UNION 
    SELECT 'Sep' month, 2013 year, 6 monthOrder UNION 
    SELECT 'Oct' month, 2013 year, 7 monthOrder UNION 
    SELECT 'Nov' month, 2013 year, 8 monthOrder UNION 
    SELECT 'Dec' month, 2013 year, 9 monthOrder UNION 
    SELECT 'Jan' month, 2014 year, 10 monthOrder UNION 
    SELECT 'Feb' month, 2014 year, 11 monthOrder UNION 
    SELECT 'Mar' month, 2014 year, 12 monthOrder UNION 
    SELECT 'Apr' month, 2014 year, 13 monthOrder
) AS a left join (
    SELECT date_entered, count(id) AS total 
    FROM leads AS b 
    WHERE user_id = 1 
    AND is_deleted = 0 
    AND date_entered BETWEEN "2013-04-29" AND "2014-04-29" 
    GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d on a.month = DATE_FORMAT(d.date_entered, "%b") 
ORDER BY a.monthOrder asc

My query's output:

--------------------------
-- month | year | total --
--   Apr | 2013 |     1 --
--   May | 2013 |     0 --
--   Jun | 2013 |     0 --
--   Jul | 2013 |     0 --
--   Aug | 2013 |     0 --
--   Sep | 2013 |     0 --
--   Oct | 2013 |     0 --
--   Nov | 2013 |     0 --
--   Dec | 2013 |     1 --
--   Jan | 2014 |     0 --
--   Feb | 2014 |     0 --
--   Mar | 2014 |     1 --
--   Apr | 2014 |     1 --
--------------------------

Because on my on a.month = DATE_FORMAT(d.date_entered, "%b") I compare the month that's why Apr 2013 has a total 1. How do I fix this issue? Can someone help me?

is there a way I can compare both month and year? How do I do that?

Thanks

War es hilfreich?

Lösung 2

You need to query year on grouping too, using WHERE a.year=DATE_FORMAT(d.date_entered, "%Y") as extra condition at top select level.

select a.month, a.year, IFNULL(d.total, 0) AS total
from (
    SELECT 'Apr' month, 2013 year, 1 monthOrder UNION 
    SELECT 'May' month, 2013 year, 2 monthOrder UNION 
    SELECT 'Jun' month, 2013 year, 3 monthOrder UNION 
    SELECT 'Jul' month, 2013 year, 4 monthOrder UNION 
    SELECT 'Aug' month, 2013 year, 5 monthOrder UNION 
    SELECT 'Sep' month, 2013 year, 6 monthOrder UNION 
    SELECT 'Oct' month, 2013 year, 7 monthOrder UNION 
    SELECT 'Nov' month, 2013 year, 8 monthOrder UNION 
    SELECT 'Dec' month, 2013 year, 9 monthOrder UNION 
    SELECT 'Jan' month, 2014 year, 10 monthOrder UNION 
    SELECT 'Feb' month, 2014 year, 11 monthOrder UNION 
    SELECT 'Mar' month, 2014 year, 12 monthOrder UNION 
    SELECT 'Apr' month, 2014 year, 13 monthOrder
) AS a left join (
    SELECT date_entered, count(id) AS total 
    FROM leads AS b 
    WHERE user_id = 1 
    AND is_deleted = 0 
    AND date_entered BETWEEN "2013-04-29" AND "2014-04-29" 
    GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d on a.month = DATE_FORMAT(d.date_entered, "%b") 
WHERE a.year=DATE_FORMAT(d.date_entered, "%Y")  -- this added
ORDER BY a.monthOrder asc

Or use AND instead of WHERE, this should have the same effectm as proposed in comments. on a.month = DATE_FORMAT(d.date_entered, "%b") AND a.year=DATE_FORMAT(d.date_entered, "%Y")

Andere Tipps

I think you should simplify and use this hack...

basically you format the date in year/month format and group by it as a string, and count.

This query alone should give you all the report you need.

select 
      concat( DATE_FORMAT(date_entered ,'%Y%m')) as `yearmonth`, 
      count(*) as `total` 
from 
      leads 
where 
      user_id=1 and 
      is_deleted = 0 and 
      date_entered BETWEEN "2013-04-29" AND "2014-04-29" 
group by 1 
order by date_entered 

Try it and tune it according to your needs. Do not add other columns because it will group by those too and you will get wrong results.

You can match 2 fields with join as per below:

SELECT a.month, a.year, IFNULL(d.total, 0) AS total
FROM (
    SELECT 'Apr' MONTH, 2013 YEAR, 1 monthOrder UNION 
    SELECT 'May' MONTH, 2013 YEAR, 2 monthOrder UNION 
    SELECT 'Jun' MONTH, 2013 YEAR, 3 monthOrder UNION 
    SELECT 'Jul' MONTH, 2013 YEAR, 4 monthOrder UNION 
    SELECT 'Aug' MONTH, 2013 YEAR, 5 monthOrder UNION 
    SELECT 'Sep' MONTH, 2013 YEAR, 6 monthOrder UNION 
    SELECT 'Oct' MONTH, 2013 YEAR, 7 monthOrder UNION 
    SELECT 'Nov' MONTH, 2013 YEAR, 8 monthOrder UNION 
    SELECT 'Dec' MONTH, 2013 YEAR, 9 monthOrder UNION 
    SELECT 'Jan' MONTH, 2014 YEAR, 10 monthOrder UNION 
    SELECT 'Feb' MONTH, 2014 YEAR, 11 monthOrder UNION 
    SELECT 'Mar' MONTH, 2014 YEAR, 12 monthOrder UNION 
    SELECT 'Apr' MONTH, 2014 YEAR, 13 monthOrder
) AS a LEFT JOIN (
    SELECT date_entered, COUNT(id) AS total 
    FROM leads AS b 
    WHERE user_id = 1 
    AND is_deleted = 0 
    AND date_entered BETWEEN "2013-04-29" AND "2014-04-29" 
    GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d ON a.month = DATE_FORMAT(d.date_entered, "%b") AND a.YEAR = DATE_FORMAT(d.date_entered, "%Y") 
ORDER BY a.monthOrder ASC
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top