【问题标题】:How to Calculate Running Averages如何计算运行平均值
【发布时间】:2021-05-18 03:28:03
【问题描述】:

场景:

我想计算迄今为止发生的整个月份的销售额的移动平均值。 每个月都有不同的天数。如果 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    

最终的moving_average 值为 (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)

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:
  1. 删除PARTITION BY
  2. Sales_Amount 上使用NULLIF(),因为您对0 不感兴趣

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


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

【讨论】:

    【解决方案2】:

    您可以尝试使用 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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        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 值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-28
          • 2019-02-07
          • 1970-01-01
          • 2011-05-17
          • 1970-01-01
          相关资源
          最近更新 更多