Reputation: 4779
I currently have a list of the top X results for a given table, for a given day, where 'top' is defined as those results with the highest aggregate count. What I want to be able to see is not just the count for that particular day, but also how it compares to yesterday's count, and the average of last week's counts.
Here is my current query:
SELECT foo, bar, SUM(count) as today
FROM tablename
WHERE col1 = 'asdf' and date = '2012-08-23'
GROUP BY foo, bar
ORDER BY count desc
LIMIT 5
The result looks something like:
|foo | bar | today |
|something1 | something3 | 2345 |
|something2 | something4 | 1234 |
....
But what I want to have is something like this:
|foo | bar | today | yesterday | week_avg |
|something1 | something3 | 2345 | 2273 | 2193 |
|something2 | something4 | 1234 | 935 | 1001 |
....
As bonus points I wouldn't mind having all the dates for the last 20 days in some kind of GROUP_CONCAT result (so I could easily make a sparkline with it)
Upvotes: 0
Views: 355
Reputation: 23125
You can get all rows from the last week, then use conditional aggregation (via CASE
expressions) to only sum the count
values of the current day and the count
values of yesterday:
SELECT foo,
bar,
SUM(CASE WHEN date = CURDATE() THEN count ELSE 0 END) AS today,
SUM(CASE WHEN date = CURDATE() - INTERVAL 1 DAY THEN count ELSE 0 END) AS yesterday,
AVG(count) AS week_avg
FROM tablename
WHERE col1 = 'asdf' AND
date >= CURDATE() - INTERVAL 1 WEEK
GROUP BY foo,
bar
ORDER BY today DESC
LIMIT 5
Finally, we order by the sum of today's count
values and select the top five based on that order.
Upvotes: 3
Reputation: 108641
Your first question. Try this:
SELECT day0.foo, day0.bar,
day0.addup as today,
day1.addup as yesterday,
week0.addup/7 as week_avg
FROM
(
SELECT foo, bar, SUM(count) as addup
FROM tablename
WHERE col1 = 'asdf'
AND date >= CURDATE()
AND date < CURDATE() + INTERVAL 1 DAY
GROUP BY foo, bar
) day0
JOIN (
SELECT foo, bar, SUM(count) as addup
FROM tablename
WHERE col1 = 'asdf'
AND date >= CURDATE() - INTERVAL 1 DAY
AND date < CURDATE()
GROUP BY foo, bar
) day1 ON (day0.foo = day1.foo AND day0.bar=day1.bar)
JOIN (
SELECT foo, bar, SUM(count) as addup
FROM tablename
WHERE col1 = 'asdf'
AND date >= CURDATE() - INTERVAL 7 DAY
AND date < CURDATE()
GROUP BY foo, bar
) week0 ON (day0.foo = week0.foo AND day0.bar = week0.bar)
ORDER BY day0.addup desc
LIMIT 5
It looks hairy, but it's the join of three different summary queries, one for each day.
Your second question:
SELECT foo, bar, GROUP_CONCAT(addup)
FROM (
SELECT foo, bar,
DATEDIFF(CURDATE(),date) AS daysago,
SUM(count) as addup
FROM tablename
WHERE col1 = 'asdf'
AND date >= CURDATE() - INTERVAL 20 DAY
AND date < CURDATE() )A
GROUP BY foo, bar, date
ORDER BY foo, bar, date
Upvotes: 0
Reputation: 34055
Once you've prepared your summary table with the date and the date's amount, and assuming you are looking for the difference from yesterday, you can use COALESCE
. The tbl
table below refers to your summary table which would look something like:
SELECT date, foo, bar, SUM(count) as today
FROM tablename
WHERE col1 = 'asdf'
GROUP BY date, foo, bar
ORDER BY count desc
LIMIT 5
The query
SELECT a.ddate, a.amount AS today,
COALESCE(a.amount -
(SELECT b.amount
FROM tbl b
WHERE b.ddate = a.ddate - INTERVAL 1 DAY), a.amount) AS yesterday
FROM tbl a
See the fiddle.
Upvotes: 0