Reputation: 1121
I have this query to count "views" in a table, by date. It obviously gives me only the dates where there has been activity, but I wish I could have MySQL return data for a selected period of time. For example 30 rows for a 30 day period, creating null data for dates where there are no matching rows.
I wish to avoid using PHP to figure this out, so I thought I'd ask here for advice on how to maybe accomplish this with a smart query.
QUERY:
SELECT count(ID) AS views, date AS view_date
FROM logging.views
WHERE date < DATE_SUB(NOW(),INTERVAL 30 DAY)
GROUP BY DAY(date)";
Example below only gives me 7 rows, obviously because there are only entries matching 7 different days in the selected 30 DAY interval. I wish I could get 30 rows representing all days in the set interval.
OUTPUT:
Array
(
[0] => Array
(
[date] => 2010-09-01 22:04:19
[views] => 20
)
[1] => Array
(
[date] => 2010-08-13 00:15:54
[views] => 4
)
[2] => Array
(
[date] => 2010-08-24 17:46:53
[views] => 2
)
[3] => Array
(
[date] => 2010-08-25 07:18:11
[views] => 35
)
[4] => Array
(
[date] => 2010-08-26 08:02:47
[views] => 12
)
[5] => Array
(
[date] => 2010-08-27 09:56:05
[views] => 29
)
[6] => Array
(
[date] => 2010-08-28 12:46:17
[views] => 30
)
)
Upvotes: 1
Views: 1417
Reputation: 562573
The common solution for this in SQL is to create a temp table with those 30 days, and LEFT OUTER JOIN
it to your views
table.
SELECT COUNT(v.ID) AS views, d.date AS view_date
FROM logging.alldays d
LEFT OUTER JOIN logging.views v ON d.date = v.date
WHERE d.date < DATE_SUB(NOW(),INTERVAL 30 DAY)
GROUP BY d.date
Or make it a non-temp table and pre-populate it with all days for the next 100 years. That's only 36525 rows, which is easy for an RDBMS.
But what if I'd wanted to query by the hour, or minute?
Then probably the temp table approach would be easier.
Basically, SQL is good at joining sets of data to other sets of data -- not joining data to thin air. So you have to make a set of data somewhere in order to join against it.
Some brands of SQL database have built-in functions to generate an ephemeral data set representing some useful range of values. For instance, PostgreSQL has generate_series()
. Unfortunately, MySQL doesn't offer this type of function.
Upvotes: 1