我有一个表Measures
,其中包含列:timestamp
(Unix时间戳),tag
,value
。
要获得15天的单一移动平均线,我可以做类似的事情:
SELECT tag,avg(value)
FROM measures
WHERE tag='xtr'
AND timestamp<1353304800
AND timestamp>1350622800
GROUP BY tag;
现在我想获得150个最新行的移动平均值,但我不确定如何查询它。
SELECT t, s,avg(bv)
FROM
(SELECT A.timestamp as t,A.tag as ta,A.value as ac, B.timestamp as tb,B.value as bv,
FROM measures
CROSS JOIN measures B
WHERE A.tag='xtr' AND B.tag='xtr'
GROUP BY A.tag) WHERE ROWNUM <= 150;
这显然是错误的,但我一直在思考它并且无法弄明白。有任何想法吗?
我的思路是,我需要将每个条目与其下方的150个条目相匹配,并计算这150个条目的value
平均值。我也很确定没有CROSS JOIN
可能会有更好的方法,因为这样会很慢。
答案 0 :(得分:6)
不完全清楚您的表结构和数据的唯一性,但此查询将为您提供所有时间戳的前150行(包括当前行)的真实移动平均值。
SELECT
tag,
timestamp,
avg(value) over (partition by tag
order by timestamp asc
rows between 149 preceding and current row) moving_avg
FROM
measures
WHERE
tag='xtr'
如果您只需要隔离最近的150行,那么请将查询基于:
select
tag,
value
from(
select tag
value
from measures
order by timestamp desc)
where
rownum <= 150
答案 1 :(得分:0)
WITH
sequenced AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY tag ORDER BY timestamp) AS sequence_id,
*
FROM
measures
)
SELECT
measure.tag,
measure.timestamp,
AVG(history.value)
FROM
sequenced AS measure
INNER JOIN
sequenced AS history
ON history.tag = measure.tag
AND history.sequence_id > measure.sequence_id - 150
AND history.sequence_id <= measure.sequence_id
GROUP BY
measure.tag,
measure.timestamp
效率不高,每行都有150个其他行加入。但这是接近它的最简单方法,我知道大多数(相对较新的)版本的ORACLE都会支持。
答案 2 :(得分:0)
Oracle有包,使用包可以编写自己的移动平均功能。
我没有足够的时间来测试应用程序但理论上它应该可以工作(仅适用于oracle)
“在整个会话期间,套餐机构中声明的变量将存活(保持其价值)。”
Create or replace package xxx ;
procedure clearMovingAverage ;
function movingAverage (newAVG in number) return number ;
end ;
/
create or replace package body xxx ;
movTot number ;
movCnt number ;
procedure clearMovingAverage is
begin
movTot := 0 ;
movCnt := 0 ;
end ;
function movingAverage (newAvg in number) return number is
begin
if newAvg is not null then
movTot := movTot + newAvg ;
movCnt := movCnt + 1 ;
end if ;
return movTot / movCnt ;
end ;
end ;
/
用法:
begin
xxx.clearMovingAverage ;
select tag,xxx.movingAverage(avg(value))
FROM measures
.....
group by tag ;
end ;
或
begin
xxx.clearMovingAverage ;
select tag, xxx.MovingAverage(avgValue)
from (select tag,avg(value) avgValue
FROM measures
.....
group by tag)
end ;
希望这段代码有用......