场景:
我想计算到目前为止发生的整个月销售额的移动平均值。 每个月都有不同的天数。如果 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)
答案 0 :(得分:3)
PARTITION BY
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
答案 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 值。