我在 Oracle 中见过很多滚动平均值的例子,但确实达到了我想要的效果。
这是我的原始数据
DATE SCORE AREA
----------------------------
01-JUL-14 60 A
01-AUG-14 45 A
01-SEP-14 45 A
02-SEP-14 50 A
01-OCT-14 30 A
02-OCT-14 45 A
03-OCT-14 50 A
01-JUL-14 60 B
01-AUG-14 45 B
01-SEP-14 45 B
02-SEP-14 50 B
01-OCT-14 30 B
02-OCT-14 45 B
03-OCT-14 50 B
Run Code Online (Sandbox Code Playgroud)
这是我的滚动平均值所需的结果
MMYY AVG AREA
-------------------------
JUL-14 60 A
AUG-14 52.5 A
SEP-14 50 A
OCT-14 44 A
JUL-14 60 B
AUG-14 52.5 B
SEP-14 50 B
OCT-14 44 B
Run Code Online (Sandbox Code Playgroud)
我需要它工作的方式是,对于每个 MMYY,我需要回顾 3 个月的情况,以及每个部门的平均分数。例如,
对于 OCT 中的 A 区,从 10 月份开始的最后 3 个月,有 6 个研究,(45+45+50+30+45+50)/6 = 44.1
通常我会像这样编写查询
SELECT
AREA,
TO_CHAR(T.DT,'MMYY') MMYY,
ROUND(AVG(SCORE)
OVER (PARTITION BY AREA ORDER BY TO_CHAR(T.DT,'MMYY') ROWS BETWEEN 2 PRECEDING AND CURRENT ROW),1)
AS AVG
FROM T
Run Code Online (Sandbox Code Playgroud)
这将查看最近 3 个条目,而不是最近 3 个月
实现此目的的一种方法是将聚合函数与分析函数混合。平均值的关键思想是避免使用avg(),而是除以sum()a count(*)。
SELECT AREA, TO_CHAR(T.DT, 'MMYY') AS MMYY,
SUM(SCORE) / COUNT(*) as AvgScore,
SUM(SUM(SCORE)) OVER (PARTITION BY AREA ORDER BY MAX(T.DT) ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) / SUM(COUNT(*)) OVER (PARTITION BY AREA ORDER BY MAX(T.DT) ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM t
GROUP BY AREA, TO_CHAR(T.DT, 'MMYY') ;
Run Code Online (Sandbox Code Playgroud)
请注意该order by条款。如果您的数据跨越数年,那么使用 MMYY 格式会带来问题。最好使用 YYYY-MM 等月份格式,因为字母顺序与自然顺序相同。
| 归档时间: |
|
| 查看次数: |
18262 次 |
| 最近记录: |