Question

Here's an sql query I am using to get count of records in a table separated by week (only date is stored in table). It works as expected.

SELECT count(id), CONCAT('Week ',WEEK(complaintRaisedDate)) week
FROM events
WHERE categoryId=1
GROUP BY week
ORDER BY week

This yields result like

count(id)       week
---------- | ----------

1               Week 36
2               Week 40
1               Week 41

How I want the result to be is below:

count(id)       week
---------- | ----------
1               Week 36
0               Week 37
0               Week 38
0               Week 39
2               Week 40
1               Week 41

That is, if no records found for a particular week it should still show the week (within the date range of records in table) with a count of 0. I can figure out a way to do this in PHP, but I was wondering if it can be achieved with a little tweaking of the SQL query itself. Is it possible? Thanks.

Edit: SQLFiddle

Was it helpful?

Solution

Assuming you have a table of integers (called `numbers` below):

   SELECT COALESCE(n, 0) AS num_complaints, CONCAT('Week ', i) AS `week`
     FROM (SELECT i
             FROM numbers
            WHERE i BETWEEN (SELECT WEEK(MIN(complaintRaisedDate)) FROM events LIMIT 1)
                            AND
                            (SELECT WEEK(MAX(complaintRaisedDate)) FROM events LIMIT 1))
          week_ranges
LEFT JOIN (  SELECT count(id) AS n, WEEK(complaintRaisedDate) AS weeknum
               FROM events
              WHERE categoryId=1
           GROUP BY weeknum) weekly_tallies
       ON week_ranges.i = weekly_tallies.weeknum
 ORDER BY `week` ASC;

SQL fiddle

OTHER TIPS

Try: http://sqlfiddle.com/#!2/5dfbf/36

CREATE  TABLE weeks (
         id INT
       );
INSERT INTO weeks (id) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (44), (45), (46), (47), (48), (49), (50), (51), (52), (53), (54);



    SELECT count(events.id), ifnull(CONCAT('Week ',WEEK(complaintRaisedDate)),0) week
FROM events RIGHT OUTER JOIN weeks ON WEEK(events.complaintRaisedDate) = weeks.id
GROUP BY weeks.id 
HAVING weeks.id>=(SELECT MIN(WEEK(events.complaintRaisedDate)) FROM events)
AND weeks.id<=(SELECT MAX(WEEK(events.complaintRaisedDate)) FROM events);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top