Reputation: 329
I want to compute some stats (with a MySQL backend) sorted by date and with dynamic intervals (week, month, year). Here is a little example :
Mysql table : tracker_click
| ID | SITE_ID | CREATED_AT |
| ---- |---------| --------------------|
| 153 | 2 | 2013-07-22 15:43:25 |
| 154 | 2 | 2013-07-25 16:45:46 |
| 2501 | 2 | 2013-09-15 17:45:48 |
I want to get the total click number by SITE_ID by week for the last month with one query And the same thing by month for the last year.
An example of what I want by week for the last month is :
| click number | SITE_ID | BEGIN_DATE | END_DATE |
|----------------|---------|----------------------|---------------------|
| 25 | 2 | 2013-07-01 00:00:00 | 2013-07-08 00:00:00 |
| 19 | 2 | 2013-08-09 00:00:00 | 2013-08-16 00:00:00 |
| 53 | 2 | 2013-0717- 00:00:00 | 2013-08-24 00:00:00 |
I don’t know if there is a solution to get exaclty this array with only one query without any other processes.
Thank you
Upvotes: 0
Views: 155
Reputation: 21513
This should get you the counts for the last month (ie, last 4 weeks), including weeks where the count is 0 for each site id. If you have a table of sites to get the site id from it means the cross join to the sub query can be replaced with a simple cross join to a table.
This generates a range of numbers from 0 to 5 and subtracts that number of weeks from the current date, formats that to give the Sunday and Saturday of the resulting week and checks that the resuling week is a week between the current date and the current date minus 1 month (done this way rather that just subtracting 4 weeks to cope with variable length months).
SELECT Weeks.aWeek_start, Weeks.aWeek_end, all_site_id.site_id, COUNT(tracker_click.id)
FROM
(
SELECT STR_TO_DATE(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL units.i WEEK), '%Y%U Sunday 00:00:00'), '%X%V %W %H:%i:%s') AS aWeek_start,
STR_TO_DATE(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL units.i WEEK), '%Y%U Saturday 23:59:59'), '%X%V %W %H:%i:%s') AS aWeek_end
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5)units
WHERE DATE_FORMAT(DATE_SUB(NOW(), INTERVAL units.i WEEK), '%Y%U') BETWEEN DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH), '%Y%U') AND DATE_FORMAT(NOW(), '%Y%U')
) Weeks
CROSS JOIN
(
SELECT DISTINCT site_id
FROM tracker_click
) AS all_site_id
LEFT OUTER JOIN tracker_click
ON tracker_click.CREATED_AT BETWEEN Weeks.aWeek_start AND Weeks.aWeek_end
AND tracker_click.site_id = all_site_id.site_id
GROUP BY Weeks.aWeek_start, Weeks.aWeek_end, all_site_id.site_id
A similar query could be done for months of the year
SELECT Months.aMonth_start, Months.aMonth_end, all_site_id.site_id, COUNT(tracker_click.id)
FROM
(
SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL units.i MONTH), '%Y/%m/01 00:00:00') AS aMonth_start,
DATE_FORMAT(LAST_DAY(DATE_SUB(NOW(), INTERVAL units.i MONTH)), '%Y/%m/%d 23:59:59') AS aMonth_end
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 UNION SELECT 10 UNION SELECT 11)units
) Months
CROSS JOIN
(
SELECT DISTINCT site_id
FROM tracker_click
) AS all_site_id
LEFT OUTER JOIN tracker_click
ON tracker_click.CREATED_AT BETWEEN Months.aMonth_start AND Months.aMonth_end
AND tracker_click.site_id = all_site_id.site_id
GROUP BY Months.aMonth_start, Months.aMonth_end, all_site_id.site_id
Upvotes: 2
Reputation: 1260
SELECT count(*), site_id, extract(WEEK from created_at) as start_date,
date_add(extract(WEEK from created_at), 1, week) as end_date
FROM click_tracker
GROUP BY site_id, extract(WEEK from created_at)
and you can add where clause to filter results additionally.
Upvotes: 0