如何计算运行平均值

时间:2021-05-17 02:38:31

标签: sql sql-server tsql

场景:

我想计算到目前为止发生的整个月销售额的移动平均值。 每个月都有不同的天数。如果 sales_amount 为 0,则表示该人请假,我需要忽略该值。

示例数据:

sales_amount    date         
100            2021-04-01    
200            2021-04-02    
300            2021-04-03    
0              2021-04-04    
100            2021-04-05    

最终的移动平均值是 (100 + 200 + 300 + 100) / (4),因为我们忽略了 4 月 4 日,因为它的销售额为 0。

我在本网站上发现的内容不符合我的需要: https://www.sqlservercentral.com/articles/calculate-moving-averages-using-t-sql-in-sql-server 但它有一定的天数,当每个月有不同的天数并且我想忽略某些行时,我该如何应用它?

预期结果:

sales_amount    date         moving_average
100            2021-04-01    100
200            2021-04-02    150
300            2021-04-03    200
0              2021-04-04    200
100            2021-04-05    175 

我尝试做的事情:

AVG (Sales_Amount) OVER (
Partition BY [Date]
Order by [Date]
,Rows Between Unbounded Preceding and Current Row)

4 个答案:

答案 0 :(得分:3)

  1. 删除 PARTITION BY
  2. NULLIF()上使用Sales_Amount,因为您对0不感兴趣

ROWS 之前还有一个额外的逗号


AVG ( NULLIF(Sales_Amount, 0) ) 
    OVER 
    (
        Order by [Date]
        Rows Between Unbounded Preceding and Current Row
    )

答案 1 :(得分:3)

您可以尝试使用 2 个聚合窗口函数来实现,一个用于计算逻辑,另一个用于累积 sales_amount

SELECT *,
       SUM(sales_amount) OVER(Order by [Date])/
       SUM(CASE WHEN sales_amount<>0 THEN 1 ELSE 0 END) OVER(Order by [Date]) moving_average
FROM T

sqlfiddle

答案 2 :(得分:1)

您在 ROWS 之前有语法错误,不需要按日期分区。但实际上并不需要 ROWS。这应该做你想做的:

AVG(NULLIF(Sales_Amount, 0)) OVER (Order by [Date])

如果您有重复的日期,那么您可能需要指定一个窗口框架——但您需要解释如何处理重复的日期。

答案 3 :(得分:0)

您可以使用相关查询,这样对于小于外部查询的内部查询的所有日期都被考虑进行平均计算。

SELECT [sales_amount], [date], 
      (SELECT AVG(NULLIF(T2.sales_amount, 0)) 
       FROM your_table T2 
       WHERE T2.orderdate <= T1.orderdate
      ) AS 'moving_average'
FROM your_table T1
ORDER BY T1.date

它将考虑 [date] 小于或等于当前行 [date] 的所有行并计算它们的平均值。正如@Squirrel 所提到的,NULLIF(T2.sales_amount, 0) 应该在平均计算中跳过 0 值。

相关问题