Question

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!

Was it helpful?

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

OTHER TIPS

If you assume that you have some data for every hour, you can move the conditional part into the select:

SELECT HOUR(dateAdded) AS HOUR ,
       COUNT(DISTINCT CASE WHEN accessMask =  '1iczo' AND destination =  'lp_include.php'
                      THEN CONCAT(remoteAddr, ',', xForwardedFor)
             END) AS cnt
FROM Track
WHERE dateAdded BETWEEN  '2014-05-01' AND '2014-05-02'
GROUP BY HOUR
ORDER BY HOUR;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top