计算滚动 180 天平均值

Calculate rolling 180 days average

我们有一个包含 TXN_DATE 和 NO_OF_TXNS 列的 table。以下是示例数据:

TXN_DATE           NO_OF_TXNS
25-AUG-19             0
26-AUG-19             1000
27-AUG-19             1500
28-AUG-19             1800
29-AUG-19             1100
30-AUG-19             1400

我们要计算过去 180 天(不包括周末)的交易滚动平均值。如果是第 1 天,平均值将等于当天的交易数量,如果是第 2 天,则平均值将等于 (n1+n2)/2,第 3 天将等于 (n1+n2+n3) )/3 等等。

任何帮助将不胜感激。

你可以试试这个。首先你需要从列表中过滤掉周末,因为在你的问题中你想找到最后 180 days excluding weekends 的记录。为了获得 days name 的日期,我们使用 TO_CHAR,为了确保它会读作英语,我们将添加 'NLS_DATE_LANGUAGE=English'.

获得列表后,您可以简单地过滤 180 条记录进行计算。为此,您可能有多种方法,例如 toprow_numberlimit 等。我使用的是 row_number。所以最终的示例代码将是这样的。

with record ( SLNO, TXN_DATE, NO_OF_TXNS ) AS 
( 
     SELECT ROW_NUMBER() OVER (ORDER BY TXN_DATE DESC) AS SLNO,
            TXN_DATE,
            NO_OF_TXNS
     FROM   TABLE 
     WHERE  TO_CHAR(TXN_DATE,'DY', 'NLS_DATE_LANGUAGE=English') NOT IN ('SAT', 'SUN') 
)
select TXN_DATE,
       NO_OF_TXNS, 
       (select avg(t.NO_OF_TXNS) from record t where t.TXN_DATE<=t1.TXN_DATE
and t.SLNO<180) as Sum 
from record t1 

感谢@WernfriedDomscheit 的改进。

您可以使用分析函数,我会避免使用行优先运算符,因为如果条目丢失一天或多天,它不会给出准确的结果,因此最好使用 WHERE 子句来获取最近 180 天。

SELECT TXN_DATE,
       AVG(NO_OF_TXNS) OVER (ORDER BY TXN_DATE) AS ROLLING_AVERAGE
  FROM YOUR_TABLE
 WHERE TO_CHAR(TXN_DATE,'DY') NOT IN ('SAT','SUN')
   AND TRUNC(TXN_DATE) >= TRUNC(SYSDATE) - 180

干杯!!

您可以使用带有 RANGE window 的解析函数。您还可以使用 TXN_DATE - TRUNC( TXN_DATE, 'IW' ) 来查找自 ISO 周(始终从星期一开始)开始以来的一周天数,这意味着您的查询不依赖于特定语言或会话参数(每个用户可以在他们的会话中更改并将语言更改为 TO_CHAR 没有给出一周中几天的预期输出)。

SELECT TXN_DATE,
       AVG( NO_OF_TXNS ) OVER (
         ORDER BY TXN_DATE
         RANGE BETWEEN 180 PRECEDING
               AND     0   PRECEDING
       ) AS avg_no_of_txns
FROM   table_name
WHERE  NOT ( TXN_DATE - TRUNC( TXN_DATE, 'IW' ) BETWEEN 5 AND 7 );

如果您想将其限制为过去 180 天的数据,那么您需要找到平均值,然后再进行过滤:

SELECT *
FROM   (
  SELECT TXN_DATE,
         AVG( NO_OF_TXNS ) OVER (
           ORDER BY TXN_DATE
           RANGE BETWEEN 180 PRECEDING
                 AND     0   PRECEDING
         ) AS avg_no_of_txns
  FROM   table_name
  WHERE  NOT ( TXN_DATE - TRUNC( TXN_DATE, 'IW' ) BETWEEN 5 AND 7 )
)
WHERE TXN_DATE >= TRUNC( SYSDATE ) - INTERVAL '180' DAY(3);

db<>fiddle