在上一个交易日的平均值计算中排除零或零

时间:2019-10-24 14:43:02

标签: sql sql-server azure-sql-database

我以为我知道了,但实际上没有。处理一些交易数据,仅需要计算交易日的平均股价。将以下查询用于3天平均值;但最近发现交易假期中可能会有股息;因此,在事实表中的那几天,都有股票代码的数据,并且收盘价为零或为空。

请帮助我改进查询,以忽略前三个交易日平均计算中的零和空值

select StockCode, datekey, ClosePrice, 
AVG(ClosePrice) OVER (partition by StockCode order by datekey 
ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING) Avg3Days
from Fact

2 个答案:

答案 0 :(得分:1)

假设您有一个指示交易日的标记,则可以执行以下操作:

SELECT StockCode, datekey, ClosePrice, 
       (CASE WHEN isTradingDay = 1
             THEN AVG(ClosePrice) OVER (PARTITION BY StockCode, isTradingDay
                                        ORDER BY datekey 
                                        ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING
                                       )
        END) as Avg3Days
FROM Fact;

这需要前三个交易日的平均值。非交易日的值为NULL

如果StockCodeNULL,则无论如何都不会将其包括在平均值中。如果唯一的指标是closePrice,则一种方法是:

SELECT f.StockCode, f.datekey, f.ClosePrice, 
       (CASE WHEN v.isTradingDay = 1
             THEN AVG(f.ClosePrice) OVER (PARTITION BY f.StockCode, v.isTradingDay
                                          ORDER BY f.datekey 
                                          ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING
                                         )
        END) as Avg3Days
FROM Fact f CROSS APPLY
     (VALUES (CASE WHEN f.ClosePrice > 0 THEN 1 ELSE 0 END)
     ) v(isTradingDay);

就个人而言,我希望有一个明确的交易日指标,而不是依靠收盘价的特殊值。例如,由于某些公司特定原因,一只股票的交易可能会暂停。

您可能还需要WHERE f.StockCode <> ''来过滤掉无效的股票代码。

答案 1 :(得分:1)

您可以按StockCodesign(NullIf([ClosePrice],0))进行分区,而不必知道交易日。

示例

Declare @YourTable Table ([datekey] date,[StockCode] varchar(50),[ClosePrice] money)  
Insert Into @YourTable Values 
 ('2019-06-15','xyx',5)
,('2019-06-16','xyx',10)
,('2019-06-17','xyx',NULL)
,('2019-06-18','xyx',0)
,('2019-06-19','xyx',15)
,('2019-06-20','xyx',20)

Select * 
     ,AvgPrice = AVG(ClosePrice) over (partition by StockCode,sign(NullIf([ClosePrice],0)) order By datekey rows between 3 preceding and 1 preceding  )      
from @YourTable
Order By datekey

返回

datekey     StockCode   ClosePrice  AvgPrice
2019-06-15  xyx         5.00        NULL
2019-06-16  xyx         10.00       5.00
2019-06-17  xyx         NULL        NULL
2019-06-18  xyx         0.00        NULL
2019-06-19  xyx         15.00       7.50
2019-06-20  xyx         20.00       10.00

更新

有点难看,但也许是这样的

Select * 
     ,AvgPrice = case when sum(1)          over (partition by StockCode,sign(NullIf([ClosePrice],0)) order By datekey rows between 3 preceding and 1 preceding  ) = 3
                      then avg(ClosePrice) over (partition by StockCode,sign(NullIf([ClosePrice],0)) order By datekey rows between 3 preceding and 1 preceding  )      
                      else null end
from @YourTable
Order By datekey

返回

enter image description here