Get average of last 7 days

自作多情 提交于 2020-05-14 10:31:30

问题


I'm attacking a problem, where I have a value for a a range of dates. I would like to consolidate the rows in my table by averaging them and reassigning the date column to be relative to the last 7 days. My SQL experience is lacking and could use some help. Thanks for giving this a look!!

E.g. 7 rows with dates and values.

UniqueId    Date      Value
........    ....     .....
  a       2014-03-20   2
  a       2014-03-21   2
  a       2014-03-22   3
  a       2014-03-23   5
  a       2014-03-24   1
  a       2014-03-25   0
  a       2014-03-26   1

Resulting row

UniqueId    Date      AvgValue
........    ....      ........
  a       2014-03-26   2

First off I am not even sure this is possible. I'm am trying to attack a problem with this data at hand. I thought maybe using a framing window with a partition to roll the dates into one date with the averaged result, but am not exactly sure how to say that in SQL.


回答1:


Am taking following as sample

CREATE TABLE some_data1 (unique_id text, date date, value integer);

INSERT INTO some_data1 (unique_id, date, value) VALUES 
 ( 'a', '2014-03-20', 2),
 ( 'a', '2014-03-21', 2),
 ( 'a', '2014-03-22', 3),
 ( 'a', '2014-03-23', 5),
 ( 'a', '2014-03-24', 1),
 ( 'a', '2014-03-25', 0),
 ( 'a', '2014-03-26', 1),
 ( 'b', '2014-03-01', 1),
 ( 'b', '2014-03-02', 1),
 ( 'b', '2014-03-03', 1),
 ( 'b', '2014-03-04', 1),
 ( 'b', '2014-03-05', 1),
 ( 'b', '2014-03-06', 1),
 ( 'b', '2014-03-07', 1)

OPTION A : - Using PostgreSQL Specific Function WITH

with cte as (
select unique_id
      ,max(date) date 
from some_data1 
group by unique_id
)
select max(sd.unique_id),max(sd.date),avg(sd.value)
from some_data1 sd inner join cte using(unique_id)
where sd.date <=cte.date 
group by cte.unique_id
limit 7 

> SQLFIDDLE DEMO


OPTION B : - To work in PostgreSQL and MySQL

select max(sd.unique_id)
      ,max(sd.date)
      ,avg(sd.value) 
from (
      select unique_id
            ,max(date) date 
      from some_data1 
      group by unique_id
     ) cte inner join some_data1 sd using(unique_id)
where sd.date <=cte.date 
group by cte.unique_id
limit 7 

> SQLFDDLE DEMO




回答2:


Maybe something along the lines of SELECT AVG(Value) AS 'AvgValue' FROM tableName WHERE Date BETWEEN dateStart AND dateEnd That will get you the average between those dates and you have dateEnd already so you could use that result to create the row you're looking for.




回答3:


For PostgreSQL a window function might be what you want:

DROP TABLE IF EXISTS some_data;

CREATE TABLE some_data (unique_id text, date date, value integer);

INSERT INTO some_data (unique_id, date, value) VALUES 
 ( 'a', '2014-03-20', 2),
 ( 'a', '2014-03-21', 2),
 ( 'a', '2014-03-22', 3),
 ( 'a', '2014-03-23', 5),
 ( 'a', '2014-03-24', 1),
 ( 'a', '2014-03-25', 0),
 ( 'a', '2014-03-26', 1),
 ( 'a', '2014-03-27', 3);

WITH avgs AS (
    SELECT unique_id, date, 
        avg(value) OVER w AS week_avg,
        count(value) OVER w AS num_days
    FROM some_data
    WINDOW w AS (
        PARTITION BY unique_id 
        ORDER BY date 
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW))
SELECT unique_id, date, week_avg
FROM avgs
WHERE num_days=7 

Result:

 unique_id |    date    |      week_avg      
-----------+------------+--------------------
 a         | 2014-03-26 | 2.0000000000000000
 a         | 2014-03-27 | 2.1428571428571429

Questions include:

  1. What happens if a day from the preceding six days is missing? Do we want to add it and count it as zero?
  2. What happens if you add a day? Is the result of the code above what you want (a rolling 7-day average)?



回答4:


For SQL Server, you can follow the below approach. Try this

1. For weekly value's average

SET DATEFIRST 4
;WITH CTE AS
(
    SELECT *,
    DATEPART(WEEK,[DATE])WK,
    --Find last day in that week 
    ROW_NUMBER() OVER(PARTITION BY UNIQUEID,DATEPART(WEEK,[DATE]) ORDER BY [DATE] DESC) RNO,
    -- Find average value of that week
    AVG(VALUE) OVER(PARTITION BY UNIQUEID,DATEPART(WEEK,[DATE])) AVGVALUE
    FROM DATETAB
)
SELECT UNIQUEID,[DATE],AVGVALUE
FROM CTE
WHERE RNO=1
  • Click here to view result

2. For last 7 days value's average

    DECLARE @DATE DATE = '2014-03-26'

    ;WITH CTE AS
    (
        SELECT UNIQUEID,[DATE],VALUE,@DATE CURRENTDATE 
        FROM DATETAB
        WHERE [DATE] BETWEEN DATEADD(DAY,-7,@DATE) AND @DATE
    )
    SELECT UNIQUEID,CURRENTDATE [DATE],AVG(VALUE) AVGVALUE
    FROM CTE
    GROUP BY UNIQUEID,CURRENTDATE
  • Click here to view result


来源:https://stackoverflow.com/questions/28101838/get-average-of-last-7-days

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!