简体   繁体   中英

Generate list of dates and count online posts each day

I want to receive results like the sample output. Listed each day beween two dates and the number of online posts from a company.

For example:

TABLE 
id  | online_From  | online_To  | comp_id  
11  | 2014-04-02   | 2014-04-05 | 20
12  | 2014-04-11   | 2014-04-16 | 21 
13  | 2014-04-03   | 2014-04-07 | 20
17  | 2014-04-29   | 2014-04-30 | 23
19  | 2014-04-04   | 2014-04-11 | 20

I want to receive:

SAMPLE OUTPUT 
2014-04-01 | 0 
2014-04-02 | 1 
2014-04-03 | 2 
2014-04-04 | 3 
2014-04-05 | 3 
2014-04-06 | 2 
2014-04-07 | 2
2014-04-08 | 1 
2014-04-09 | 1 
2014-04-10 | 1
2014-04-11 | 1 
2014-04-12 | 0 
2014-04-13 | 0
…
2014-05-07 | 0 

I used this mysql code to list the requested dates (and also split into y/m/d/w for generate charts):

select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) 
selected_date from (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,  
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v 
where selected_date between '2014-04-01' and '2014-05-07' 
GROUP BY y,m,d ORDER BY y ASC, m ASC, d ASC


2014-04-01|2014 |1 |14 |4 |0
2014-04-02|2014 |2 |14 |4 |1 
2014-04-03|2014 |3 |14 |4 |2
…

This comes from: How to get list of dates between two dates in mysql select query

I tried a lot of things but I never became the hoped result. I want to loop trough the dates and check the number of posts that where online that day.

Hopefully somebody can help me!

Thanks

This should get you started if you want a SQL-only answer. Have called your table comp_table ...

select d.selected_date,d.d,d.m,d.y,
count(ct.id)
from 
(
 select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m from
 (select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) 
 selected_date from (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,  
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v 
 where selected_date between '2014-04-01' and '2014-05-07' 
 GROUP BY selected_date
) d 
left outer join comp_table ct on d.selected_date between ct.online_From and ct.online_To
group by d.selected_date
order by 1 asc
;

You might be better off periodically populating an all_dates table to use in place of the inline view though. Would be more performant!

EDIT

If you want to maintain 'gimme all dates even if they have a 0 count' yet filter the results eg by the comp_id column then simply change the left outer join to include your filter by clause. For example:

select d.selected_date,d.d,d.m,d.y,
count(ct.id)
from 
(
 select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m from
 (select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) 
 selected_date from (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,  
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3, 
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v 
 where selected_date between '2014-04-01' and '2014-05-07' 
 GROUP BY selected_date
) d 
left outer join comp_table ct 
     on d.selected_date between ct.online_From and ct.online_To 
        and ct.comp_id = 20
group by d.selected_date
order by 1 asc
;

If you have not already installed it, I recommend you install common_schema . Once that's installed you can use the numbers table to simplify your query.

For example this query should give you the desired output:

select days.day,count(distinct your_table.id) from 
(
  select '2014-04-01' + interval n day AS day
  from common_schema.numbers
  having day between '2014-04-01' and '2014-05-07'
) days
  left outer join your_table on your_table.online_From <= days.day and your_table.online_To >= days.day
group by days.day
order by days.day

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM