Home All Groups Group Topic Archive Search About

How to calculate a 5 minute running average?

Author
11 Sep 2006 9:15 PM
Jeff Richardson
I have a table that records temperatures every minute or so.  There is a
datetime (Sample_Date) that stores the time a temperature was read and a
float (Sample_Value) that stores the temperature.

I'm trying to write an UPDATE statement to calculate the average of the
previously 5 minutes worth of readings and store it in another float
(Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
records with the same value.

Update MaterialMonitoringExpanded
Set Sample_Avg = (
        SELECT avg(sub.Sample_Value)
        FROM   MaterialMonitoringExpanded as sub
        WHERE  (sub.Logging_Index = Logging_Index) AND
                       (sub.Sample_Date >= Sample_Date - .003472) AND
                       (sub.Sample_Date <= Sample_Date)
         )
WHERE (Logging_Index = 23)

The .003472 represents 5 minutes (is there a better way to substract 5
minutes from a datetime?)

What am doing wrong with this query?

Thanks in advance
Jeff.

Author
11 Sep 2006 9:35 PM
Warren Brunk
I would use the dateadd function

http://msdn2.microsoft.com/en-us/library/ms186819.aspx

Update MaterialMonitoringExpanded
Set Sample_Avg = (
        SELECT avg(sub.Sample_Value)
        FROM   MaterialMonitoringExpanded as sub
        WHERE  (sub.Logging_Index = Logging_Index) AND
                       (sub.Sample_Date >= DateAdd(Minute,-5,Sample_Date)
AND
                       (sub.Sample_Date <= Sample_Date)
         )
WHERE (Logging_Index = 23)



--
/*
Warren Brunk - MCITP - SQL 2005, MCDBA
www.techintsolutions.com
*/


Show quote
"Jeff Richardson" <BobcatRidge@newsgroups.nospam> wrote in message
news:uAsLcde1GHA.5048@TK2MSFTNGP05.phx.gbl...
>I have a table that records temperatures every minute or so.  There is a
>datetime (Sample_Date) that stores the time a temperature was read and a
>float (Sample_Value) that stores the temperature.
>
> I'm trying to write an UPDATE statement to calculate the average of the
> previously 5 minutes worth of readings and store it in another float
> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
> records with the same value.
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg = (
>        SELECT avg(sub.Sample_Value)
>        FROM   MaterialMonitoringExpanded as sub
>        WHERE  (sub.Logging_Index = Logging_Index) AND
>                       (sub.Sample_Date >= Sample_Date - .003472) AND
>                       (sub.Sample_Date <= Sample_Date)
>         )
> WHERE (Logging_Index = 23)
>
> The .003472 represents 5 minutes (is there a better way to substract 5
> minutes from a datetime?)
>
> What am doing wrong with this query?
>
> Thanks in advance
> Jeff.
>
Author
11 Sep 2006 9:46 PM
Jeff Richardson
Warren,
Thanks for the help with the DateAdd function, much cleaner!

Do you have any idea why this query sets all the records with the same value
in Sample_Avg?  I want it calc the average for the pervious 5 minutes of
data, therefore the average should change with time.

Thanks
Jeff.
Show quote
"Warren Brunk" <wbr***@techintsolutions.com> wrote in message
news:eO%23uHpe1GHA.2196@TK2MSFTNGP06.phx.gbl...
>I would use the dateadd function
>
> http://msdn2.microsoft.com/en-us/library/ms186819.aspx
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg = (
>        SELECT avg(sub.Sample_Value)
>        FROM   MaterialMonitoringExpanded as sub
>        WHERE  (sub.Logging_Index = Logging_Index) AND
>                       (sub.Sample_Date >= DateAdd(Minute,-5,Sample_Date)
> AND
>                       (sub.Sample_Date <= Sample_Date)
>         )
> WHERE (Logging_Index = 23)
>
>
>
> --
> /*
> Warren Brunk - MCITP - SQL 2005, MCDBA
> www.techintsolutions.com
> */
>
>
> "Jeff Richardson" <BobcatRidge@newsgroups.nospam> wrote in message
> news:uAsLcde1GHA.5048@TK2MSFTNGP05.phx.gbl...
>>I have a table that records temperatures every minute or so.  There is a
>>datetime (Sample_Date) that stores the time a temperature was read and a
>>float (Sample_Value) that stores the temperature.
>>
>> I'm trying to write an UPDATE statement to calculate the average of the
>> previously 5 minutes worth of readings and store it in another float
>> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
>> records with the same value.
>>
>> Update MaterialMonitoringExpanded
>> Set Sample_Avg = (
>>        SELECT avg(sub.Sample_Value)
>>        FROM   MaterialMonitoringExpanded as sub
>>        WHERE  (sub.Logging_Index = Logging_Index) AND
>>                       (sub.Sample_Date >= Sample_Date - .003472) AND
>>                       (sub.Sample_Date <= Sample_Date)
>>         )
>> WHERE (Logging_Index = 23)
>>
>> The .003472 represents 5 minutes (is there a better way to substract 5
>> minutes from a datetime?)
>>
>> What am doing wrong with this query?
>>
>> Thanks in advance
>> Jeff.
>>
>
>
Author
11 Sep 2006 9:39 PM
Warren Brunk
Does this syntax work better?

Update MaterialMonitoringExpanded
Set Sample_Avg =  avg(sub.Sample_Value)
FROM   MaterialMonitoringExpanded as sub
WHERE   (sub.Sample_Date >= Sample_Date - .003472) AND
                  (sub.Sample_Date <= Sample_Date)

--
/*
Warren Brunk - MCITP - SQL 2005, MCDBA
www.techintsolutions.com
*/


Show quote
"Jeff Richardson" <BobcatRidge@newsgroups.nospam> wrote in message
news:uAsLcde1GHA.5048@TK2MSFTNGP05.phx.gbl...
>I have a table that records temperatures every minute or so.  There is a
>datetime (Sample_Date) that stores the time a temperature was read and a
>float (Sample_Value) that stores the temperature.
>
> I'm trying to write an UPDATE statement to calculate the average of the
> previously 5 minutes worth of readings and store it in another float
> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
> records with the same value.
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg = (
>        SELECT avg(sub.Sample_Value)
>        FROM   MaterialMonitoringExpanded as sub
>        WHERE  (sub.Logging_Index = Logging_Index) AND
>                       (sub.Sample_Date >= Sample_Date - .003472) AND
>                       (sub.Sample_Date <= Sample_Date)
>         )
> WHERE (Logging_Index = 23)
>
> The .003472 represents 5 minutes (is there a better way to substract 5
> minutes from a datetime?)
>
> What am doing wrong with this query?
>
> Thanks in advance
> Jeff.
>
Author
11 Sep 2006 10:11 PM
Jeff Richardson
I get the following syntax error when I try to run the query:

Msg 157, Level 15, State 1, Line 1
An aggregate may not appear in the set list of an UPDATE statement.


Show quote
"Warren Brunk" <wbr***@techintsolutions.com> wrote in message
news:%237GKHre1GHA.4632@TK2MSFTNGP03.phx.gbl...
> Does this syntax work better?
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg =  avg(sub.Sample_Value)
> FROM   MaterialMonitoringExpanded as sub
> WHERE   (sub.Sample_Date >= Sample_Date - .003472) AND
>                  (sub.Sample_Date <= Sample_Date)
>
> --
> /*
> Warren Brunk - MCITP - SQL 2005, MCDBA
> www.techintsolutions.com
> */
>
>
> "Jeff Richardson" <BobcatRidge@newsgroups.nospam> wrote in message
> news:uAsLcde1GHA.5048@TK2MSFTNGP05.phx.gbl...
>>I have a table that records temperatures every minute or so.  There is a
>>datetime (Sample_Date) that stores the time a temperature was read and a
>>float (Sample_Value) that stores the temperature.
>>
>> I'm trying to write an UPDATE statement to calculate the average of the
>> previously 5 minutes worth of readings and store it in another float
>> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
>> records with the same value.
>>
>> Update MaterialMonitoringExpanded
>> Set Sample_Avg = (
>>        SELECT avg(sub.Sample_Value)
>>        FROM   MaterialMonitoringExpanded as sub
>>        WHERE  (sub.Logging_Index = Logging_Index) AND
>>                       (sub.Sample_Date >= Sample_Date - .003472) AND
>>                       (sub.Sample_Date <= Sample_Date)
>>         )
>> WHERE (Logging_Index = 23)
>>
>> The .003472 represents 5 minutes (is there a better way to substract 5
>> minutes from a datetime?)
>>
>> What am doing wrong with this query?
>>
>> Thanks in advance
>> Jeff.
>>
>
>
Author
11 Sep 2006 9:44 PM
Stu
In general, you should use the DATEADD function to work with dates.  Do
you need to run an UPDATE statement?  Look at the following query:

DECLARE @SCRATCH TABLE (mt smalldatetime, val float)

INSERT INTO @Scratch
SELECT '1:01', 2.33
UNION ALL
SELECT '1:02', 1.97
UNION ALL
SELECT '1:03', 3.33
UNION ALL
SELECT '1:04', 4.6788
UNION ALL
SELECT '1:05', 6.15

SELECT mt, val, (SELECT avg(val)
                FROM @scratch s2
                WHERE s2.mt BETWEEN DATEADD(minute, -3, s1.mt) AND DATEADD(minute,
-1, s1.mt))
FROM @Scratch s1


Does that help?
Stu

Jeff Richardson wrote:
Show quote
> I have a table that records temperatures every minute or so.  There is a
> datetime (Sample_Date) that stores the time a temperature was read and a
> float (Sample_Value) that stores the temperature.
>
> I'm trying to write an UPDATE statement to calculate the average of the
> previously 5 minutes worth of readings and store it in another float
> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
> records with the same value.
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg = (
>         SELECT avg(sub.Sample_Value)
>         FROM   MaterialMonitoringExpanded as sub
>         WHERE  (sub.Logging_Index = Logging_Index) AND
>                        (sub.Sample_Date >= Sample_Date - .003472) AND
>                        (sub.Sample_Date <= Sample_Date)
>          )
> WHERE (Logging_Index = 23)
>
> The .003472 represents 5 minutes (is there a better way to substract 5
> minutes from a datetime?)
>
> What am doing wrong with this query?
>
> Thanks in advance
> Jeff.
Author
11 Sep 2006 10:13 PM
Jeff Richardson
Yes, I need to do an UPDATE so that I can do some additional work on the
table.

Show quote
"Stu" <stuart.ainswo***@gmail.com> wrote in message
news:1158011061.513963.51370@b28g2000cwb.googlegroups.com...
> In general, you should use the DATEADD function to work with dates.  Do
> you need to run an UPDATE statement?  Look at the following query:
>
> DECLARE @SCRATCH TABLE (mt smalldatetime, val float)
>
> INSERT INTO @Scratch
> SELECT '1:01', 2.33
> UNION ALL
> SELECT '1:02', 1.97
> UNION ALL
> SELECT '1:03', 3.33
> UNION ALL
> SELECT '1:04', 4.6788
> UNION ALL
> SELECT '1:05', 6.15
>
> SELECT mt, val, (SELECT avg(val)
> FROM @scratch s2
> WHERE s2.mt BETWEEN DATEADD(minute, -3, s1.mt) AND DATEADD(minute,
> -1, s1.mt))
> FROM @Scratch s1
>
>
> Does that help?
> Stu
>
> Jeff Richardson wrote:
>> I have a table that records temperatures every minute or so.  There is a
>> datetime (Sample_Date) that stores the time a temperature was read and a
>> float (Sample_Value) that stores the temperature.
>>
>> I'm trying to write an UPDATE statement to calculate the average of the
>> previously 5 minutes worth of readings and store it in another float
>> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
>> records with the same value.
>>
>> Update MaterialMonitoringExpanded
>> Set Sample_Avg = (
>>         SELECT avg(sub.Sample_Value)
>>         FROM   MaterialMonitoringExpanded as sub
>>         WHERE  (sub.Logging_Index = Logging_Index) AND
>>                        (sub.Sample_Date >= Sample_Date - .003472) AND
>>                        (sub.Sample_Date <= Sample_Date)
>>          )
>> WHERE (Logging_Index = 23)
>>
>> The .003472 represents 5 minutes (is there a better way to substract 5
>> minutes from a datetime?)
>>
>> What am doing wrong with this query?
>>
>> Thanks in advance
>> Jeff.
>
Author
11 Sep 2006 10:19 PM
Erland Sommarskog
Jeff Richardson (BobcatRidge@newsgroups.nospam) writes:
Show quote
> I have a table that records temperatures every minute or so.  There is a
> datetime (Sample_Date) that stores the time a temperature was read and a
> float (Sample_Value) that stores the temperature.
>
> I'm trying to write an UPDATE statement to calculate the average of the
> previously 5 minutes worth of readings and store it in another float
> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
> records with the same value.
>
> Update MaterialMonitoringExpanded
> Set Sample_Avg = (
>         SELECT avg(sub.Sample_Value)
>         FROM   MaterialMonitoringExpanded as sub
>         WHERE  (sub.Logging_Index = Logging_Index) AND
>                        (sub.Sample_Date >= Sample_Date - .003472) AND
>                        (sub.Sample_Date <= Sample_Date)
>          )
> WHERE (Logging_Index = 23)
>
> The .003472 represents 5 minutes (is there a better way to substract 5
> minutes from a datetime?)
>
> What am doing wrong with this query?

There is no correlation between the subquery and the table being updated.
The prefixless Logging_Index refers to the sub instance of the table,
not the outer instance.

If you want to want to be strictly ANSI SQL, I think you need to writ:

  Update MaterialMonitoringExpanded
  Set Sample_Avg = (
          SELECT avg(sub.Sample_Value)
          FROM   MaterialMonitoringExpanded as sub
          WHERE  (sub.Logging_Index =
                       MaterialMonitoringExpanded.Logging_Index) AND
                  (sub.Sample_Date >=
                       MaterialMonitoringExpanded.Sample_Date - .003472) AND
                  (sub.Sample_Date <=
                       MaterialMonitoringExpanded.Sample_Date)
          )
WHERE (Logging_Index = 23)

Personally I would take advantage of that SQL Server permits a FROM
clause and define an alias:

   Update MaterialMonitoringExpanded
   Set Sample_Avg = (
           SELECT avg(sub.Sample_Value)
           FROM   MaterialMonitoringExpanded as sub
           WHERE  (sub.Logging_Index = main.Logging_Index) AND
                          (sub.Sample_Date >= main.Sample_Date - .003472)
AND
                          (sub.Sample_Date <= main.Sample_Date)
            )
   WHERE (Logging_Index = 23)
   FROM  MaterialMonitoringExpanded main


--
Erland Sommarskog, SQL Server MVP, esq***@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
Author
11 Sep 2006 10:53 PM
Jeff Richardson
Erland,

Adding the FROM clause with an alias did the job!

Thanks very much to everyone who helped.
Jeff.

Show quote
"Erland Sommarskog" <esq***@sommarskog.se> wrote in message
news:Xns983C34A2FF3FYazorman@127.0.0.1...
> Jeff Richardson (BobcatRidge@newsgroups.nospam) writes:
>> I have a table that records temperatures every minute or so.  There is a
>> datetime (Sample_Date) that stores the time a temperature was read and a
>> float (Sample_Value) that stores the temperature.
>>
>> I'm trying to write an UPDATE statement to calculate the average of the
>> previously 5 minutes worth of readings and store it in another float
>> (Sample_Avg).  Below is a UPDATE query that I wrote, but it updates all
>> records with the same value.
>>
>> Update MaterialMonitoringExpanded
>> Set Sample_Avg = (
>>         SELECT avg(sub.Sample_Value)
>>         FROM   MaterialMonitoringExpanded as sub
>>         WHERE  (sub.Logging_Index = Logging_Index) AND
>>                        (sub.Sample_Date >= Sample_Date - .003472) AND
>>                        (sub.Sample_Date <= Sample_Date)
>>          )
>> WHERE (Logging_Index = 23)
>>
>> The .003472 represents 5 minutes (is there a better way to substract 5
>> minutes from a datetime?)
>>
>> What am doing wrong with this query?
>
> There is no correlation between the subquery and the table being updated.
> The prefixless Logging_Index refers to the sub instance of the table,
> not the outer instance.
>
> If you want to want to be strictly ANSI SQL, I think you need to writ:
>
>  Update MaterialMonitoringExpanded
>  Set Sample_Avg = (
>          SELECT avg(sub.Sample_Value)
>          FROM   MaterialMonitoringExpanded as sub
>          WHERE  (sub.Logging_Index =
>                       MaterialMonitoringExpanded.Logging_Index) AND
>                  (sub.Sample_Date >=
>                       MaterialMonitoringExpanded.Sample_Date - .003472)
> AND
>                  (sub.Sample_Date <=
>                       MaterialMonitoringExpanded.Sample_Date)
>          )
> WHERE (Logging_Index = 23)
>
> Personally I would take advantage of that SQL Server permits a FROM
> clause and define an alias:
>
>   Update MaterialMonitoringExpanded
>   Set Sample_Avg = (
>           SELECT avg(sub.Sample_Value)
>           FROM   MaterialMonitoringExpanded as sub
>           WHERE  (sub.Logging_Index = main.Logging_Index) AND
>                          (sub.Sample_Date >= main.Sample_Date - .003472)
> AND
>                          (sub.Sample_Date <= main.Sample_Date)
>            )
>   WHERE (Logging_Index = 23)
>   FROM  MaterialMonitoringExpanded main
>
>
> --
> Erland Sommarskog, SQL Server MVP, esq***@sommarskog.se
>
> Books Online for SQL Server 2005 at
> http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
> Books Online for SQL Server 2000 at
> http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

AddThis Social Bookmark Button