1

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

Community
  • 1
  • 1
swebd
  • 41
  • 3

2 Answers2

1

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 e.g. 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
;
Tom Mac
  • 9,693
  • 3
  • 25
  • 35
  • I add after "left outer join comp_table ct on d.selected_date between ct.online_From and ct.online_To " --> WHERE ct.comp_id=20 because I want this from one company like in the example id=20. Is this correct? – swebd May 07 '14 at 15:51
  • I also get 2014-03-19, 2014-03-20 and than it goes to 2014-03-25. Is there a way to get also the days 21, 22, 23 & 24 even when the result is 0? – swebd May 07 '14 at 15:52
  • 1
    Sure. Remove the `where` clause and modify the `left outer join` to be `left outer join comp_table ct on d.selected_date between ct.online_From and ct.online_To and comp_id=20`. Should do the trick. Will modify my answer to illustrate this – Tom Mac May 07 '14 at 18:48
  • How can I get this results grouped by month with the average of online posts? Her can you see the result: http://sqlfiddle.com/#!2/dbc972/1 – swebd May 08 '14 at 13:35
  • Hmm. You've actually asked three questions now! Suggest you this latest question as a new SO question. Otherwise these comments are going to go on rather a lot.... – Tom Mac May 08 '14 at 13:35
0

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
Ike Walker
  • 64,401
  • 14
  • 110
  • 109