Search code examples
mysqlcoalesceisnullhour

MYSQL return 0 on hourly count


I am at a loss of how to accomplish this but have seen online ISNULL() and COALESCE() used to return a zero if the query is null. I am unsure though how to use it properly though I am intuitively thinking i need to have in a subquery then have ISNULL or COALESCE around that subquery?

The query goes:

SELECT HOUR( dateAdded ) AS HOUR , COUNT( DISTINCT remoteAddr, xForwardedFor) AS cnt
FROM Track
WHERE accessMask =  '1iczo'
AND destination =  'lp_include.php'
AND dateAdded
BETWEEN  '2014-05-01'
AND  '2014-05-02'
GROUP BY HOUR
ORDER BY HOUR

Some help in the right direction would be greatly appreciated!

UPDATE

I used what @Barmar had suggested but it wasn't returning accurate results. I used what he provided and also another topic with a similar situation, Group by should return 0 when grouping by hours. How to do this? . I actually didn't find this topic till after posting this one, :( unfortunately. Here is the final code that appears to return accurate results, distinct across two columns with empty data being returned as 0.

SELECT a.hour, COALESCE(cnt, 0) AS cnt
FROM (SELECT 0 AS hour
UNION ALL
  SELECT 1
UNION ALL
  SELECT 2 .....
UNION ALL
  SELECT 23) a
LEFT JOIN
(SELECT COUNT(DISTINCT remoteAddr, xForwardedFor) AS cnt, HOUR(dateAdded) AS hour
  FROM Track
  WHERE accessMask =  '1iczo'
  AND destination =  'lp_include.php'
  AND dateAdded
  BETWEEN  '2014-05-01 00:00:00' AND '2014-05-01 23:59:59') AS totals
ON a.hour = totals.hour

Fiddle for better reference: http://sqlfiddle.com/#!2/9ab660/7

Thanks again to @Barmar, he really put me in the right direction to get to the solution!


Solution

  • You have to join with a table that contains all the hours. This must be a LEFT JOIN so that the results will include hours that have no matches in Track table.

    SELECT allHours.hour, IFNULL(cnt, 0) AS cnt
    FROM (SELECT 0 AS hour
          UNION
          SELECT 1
          UNION
          SELECT 2
          UNION
          SELECT 3
          ...
          UNION
          SELECT 23) AS allHours
    LEFT JOIN
         (SELECT HOUR(dateAdded) AS hour, COUNT(DISTINCT remoteAddr, xForwardedFor) AS cnt
          FROM Track
          WHERE accessMask =  '1iczo'
          AND destination =  'lp_include.php'
          AND dateAdded
          BETWEEN  '2014-05-01' AND '2014-05-02') AS totals
    ON allHours.hour = totals.hour