2

I am trying to create a query which will check how many entries I have in my database for the last 7 days, it works, but it only returns the dates where records exist. I would like it to return a 0 for days where there is no data as I am producing a 7 day report.

Any help gratefully received!

SELECT DATE(created_date) AS date, 
    (SELECT COUNT(id) 
    FROM records 
    WHERE DATE(created_date) = date AND method = 'tw') AS total_records 
FROM records 
WHERE created_date > DATE_SUB(NOW(), INTERVAL 7 day) 
GROUP BY date
1

4 Answers 4

2
SELECT DATE(NOW() + INTERVAL num.i DAY) AS date, 
       COUNT(r.id) AS total_records 
FROM 
        ( SELECT 0 AS i UNION ALL               -- where 0 means today
          SELECT -1 UNION ALL                   -- and -1 is yesterday
          ...
          SELECT -6
        ) AS num
    LEFT JOIN
        records AS r
            ON  r.created_date >= DATE(NOW() + INTERVAL num.i DAY)
            AND r.created_date < DATE(NOW() + INTERVAL 1+num.i DAY)
            AND r.method = 'tw'
GROUP BY num.i ;

An index on (method, created_date) will help efficiency.

Sign up to request clarification or add additional context in comments.

Comments

1
SELECT case when created_date is null
            then 0
            else DATE(created_date)
       end AS date,
      (SELECT COUNT(id)
       FROM records
       WHERE DATE(created_date) = date 
       AND method = 'tw') AS total_records 
FROM records
WHERE created_date > DATE_SUB(NOW(), INTERVAL 7 day)
OR created_date is null
GROUP BY date

3 Comments

Thank you very much, this query works but it seems very slow (probably my own poor initial attempt is to blame!) it's taking ~10 seconds on a database with 50k records
Do you have an index on your created_date? You'll want one for this query.
The DATE(created_date) will probably make the index useless (for that part).
1

I suspect moving the subquery from the SELECT clause to the FROM clause will improve performance. However, you don't need a subquery at all, if you just want to count the tw records:

SELECT date(created_date) as date, 
       sum(case when method = 'tw' then 1 else 0 end) as total_records
FROM records 
WHERE created_date > DATE_SUB(NOW(), INTERVAL 7 day)
group by date(created_date)

This will return every day, assuming there is at least one type of record on each day. By the way, if you have a problem with created_date being NULL, then you can include the conditions suggested by Juergen.

Comments

1

Perfomance will depends of how many records you will have in 7-day interval.

select date, 
       sum(cnt) 
from (SELECT 
       count(id) as cnt, 
       date(created_date) as date
       FROM records 
      WHERE created_date > DATE_SUB(NOW(), INTERVAL 7 day)
            and method ='tw' 
            and created_date < now()
      group by date
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 6 day)) as date)
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 5 day)) as date)
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 4 day)) as date)
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 3 day)) as date)
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 2 day)) as date)
      union all (select 0 as cnt, date(DATE_SUB(NOW(), INTERVAL 1 day)) as date)
      union all (select 0 as cnt, date(NOW()) as date)
     ) t

group by date

2 Comments

Hi, this approach worked on MyISAM but not for InnoDB - is it due to the select 0? each day now returns 0 on the new sql engine. Thanks
@Jon select 0 uses to add rows with 0 sum, if table hasn't record for that day. I don't know how mysql engine can affect that query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.