Reputation: 28387
This is a follow up to: TSQL Group by N Seconds . (I got what I asked for, but didn't ask for the right thing)
How can I get a rolling average of 1 second groups of count(*)
?
So I want to return per second counts, but I also want to be able to smooth that out over certain intervals, say 10 seconds.
So one method might be to take the average per second of every 10 seconds, can that be done in TSQL?
Ideally, the time field would be returned in Unix Time.
Upvotes: 2
Views: 729
Reputation: 425341
SQL Server
is not particularly good in rolling/cumulative queries.
You can use this:
WITH q (unix_ts, cnt) AS
(
SELECT DATEDIFF(s, '1970-01-01', ts), COUNT(*)
FROM record
GROUP BY
DATEDIFF(s, '1970-01-01', ts)
)
SELECT *
FROM q q1
CROSS APPLY
(
SELECT AVG(cnt) AS smooth_cnt
FROM q q2
WHERE q2.unix_ts BETWEEN q1.unix_ts - 5 AND q1.unix_ts + 5
) q2
, however, this may not be very efficient, since it will count the same overlapping intervals over an over again.
For the larger invervals, it may be even better to use a CURSOR
-based solution that would allow to keep intermediate results (though normally they are worse performance-wise than pure set-based solutions).
Oracle
and PostgreSQL
support this clause:
WITH q (unix_ts, cnt) AS
(
SELECT TRUNC(ts, 'ss'), COUNT(*)
FROM record
GROUP BY
TRUNC(ts, 'ss')
)
SELECT q.*,
AVG(cnt) OVER (ORDER BY unix_ts RANGE BETWEEN INTERVAL '-5' SECOND AND INTERVAL '5' SECOND)
FROM q
which keeps an internal window buffer and is very efficient.
SQL Server
, unfortunately, does not support moving windows.
Upvotes: 3