I have two tables of users and articles and I want to count how many new users and how many new articles I have in the past 7 days.
tbl_users:
[Code, Username, Createdate]
1,David,01/01/2022
2,Henry,02/01/2022
tbl_articles:
[Code, Header, Createdate]
1,Hello,01/01/2022
2,Goodbye,02/01/2022
This query works now but it’s slow and long. Please help me fix this query (I know it’s bad) and if it’s possible to add diff columns for both counters:
(Please go easy on me with the comments)
select articles.days_back,articles.count, users.count as users from (
select 0 as days_back,count(*) as count from tbl_articles where date(createdate)< date_add(curdate(), interval -0 day)
union all
select 1,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -1 day)
union all
select 2,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -2 day)
union all
select 3,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -3 day)
union all
select 4,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -4 day)
union all
select 5,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -5 day)
union all
select 6,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -6 day)
union all
select 7,count(*) from tbl_articles where date(createdate)< date_add(curdate(), interval -7 day)
) as articles
left join
(
select 0 as days_back,count(*) as count from tbl_users where date(createdate)< date_add(curdate(), interval -0 day)
union all
select 1,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -1 day)
union all
select 2,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -2 day)
union all
select 3,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -3 day)
union all
select 4,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -4 day)
union all
select 5,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -5 day)
union all
select 6,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -6 day)
union all
select 7,count(*) from tbl_users where date(createdate)< date_add(curdate(), interval -7 day)
) as users
on articles.days_back=users.days_back
2
Answers
Something like that?
haven’t tested it btw
It is not as easy as just use a group by, but as you thought group by is important to do this. I guess there will be no simple 5 line query to get your expected result.
I would suggest to do multiple queries and some backend code instead of a single query. It is hard to read, understand and maintain.
But it is possible.
A
GROUP BY DATE_FORMAT(Created,'%Y-%m-%d')
in a simple select would already give you the count per day.The next problem to solve is, that you want the
days_back
instead of the date itself. Thats also quite simple withDATEDIFF(DATE_FORMAT(NOW(),'%Y-%m-%d'), DATE_FORMAT(Createdate,'%Y-%m-%d'))
.But the third requirement is the difficult. You don’t want the amount per day but the sum up to that day, for a variable amount of days back. Unfortunatly, mysql does not offer a Sequence (like SELECT numbers from 1 to X) to join with the other parts of the query. If you can live with a restriction to somewhat about 300 years, https://stackoverflow.com/a/9296238/4675841 will help there.
To get article counts and user counts together, you coult either use union (all) or a join, I used the join and came up with this query.
Try it out.