There is a table (MySQL).
It's simplified structure:
day DATE val INT UNSIGNED
I need the average val
for:
- every week containing a date from the table;
- every month containing a date from the table.
What is the simplest way to do this?
If you are looking to return the average val
for each week and every month that has a date in the table, then you can implement the following.
Sample data:
CREATE TABLE yourtable (`day` datetime, `val` int);
INSERT INTO yourtable (`day`, `val`)
VALUES
('2012-01-01 00:00:00', 465),
('2012-01-02 00:00:00', 896),
('2012-08-15 00:00:00', 678),
('2012-09-01 00:00:00', 324),
('2012-12-02 00:00:00', 74),
('2012-12-03 00:00:00', 65),
('2012-12-04 00:00:00', 35);
Weekly Average:
To get the average by week, I would GROUP BY
both the week number and the year, using the MySQL functions week()
and year()
. Then if you have data from multiple years the average will be shown by year as well (otherwise your values could be skewed). Your query would be similar to this:
select week(day) Week,
year(day) Year,
avg(val) WeekAvg
from yourtable
group by week(day), year(day)
See SQL Fiddle with Demo. The result is:
| WEEK | YEAR | WEEKAVG |
-------------------------
| 1 | 2012 | 680.5 |
| 33 | 2012 | 678 |
| 35 | 2012 | 324 |
| 49 | 2012 | 58 |
Monthly Average:
Now to get the average val
by month, you can use the MySQL functions monthname()
and year()
.
select monthname(day) Month,
year(day) Year,
avg(val) AvgValue
from yourtable
group by monthname(day), year(day)
See SQL Fiddle with Demo. The result is:
| MONTH | YEAR | AVGVALUE |
-------------------------------
| August | 2012 | 678 |
| December | 2012 | 58 |
| January | 2012 | 680.5 |
| September | 2012 | 324 |
Combined Result:
You did not specify if you want this data in the same query. But if you do, then you can easily use a UNION ALL
to consolidate the data into one result set. In the UNION ALL
query, I added a column to identify the data as either month or week (but you can remove that if needed):
select monthname(day) Month,
year(day) Year,
avg(val) AvgValue,
'MonthAvg' Source
from yourtable
group by monthname(day), year(day)
union all
select week(day) Week,
year(day) Year,
avg(val) WeekAvg,
'WeekAvg' Source
from yourtable
group by week(day), year(day)
See SQL Fiddle with Demo The UNION ALL
will produce a combined result set similar to this:
| MONTH | YEAR | AVGVALUE | SOURCE |
------------------------------------------
| August | 2012 | 678 | MonthAvg |
| December | 2012 | 58 | MonthAvg |
| January | 2012 | 680.5 | MonthAvg |
| September | 2012 | 324 | MonthAvg |
| 1 | 2012 | 680.5 | WeekAvg |
| 33 | 2012 | 678 | WeekAvg |
| 35 | 2012 | 324 | WeekAvg |
| 49 | 2012 | 58 | WeekAvg |