簡體   English   中英

SQL 服務器:解析 window function 不同長度

[英]SQL Server: Analytic window function with varying lengths

我想在幾個不同長度的 windows 上編寫一個帶有聚合函數的分析 function。 假設我有一張股票收盤價表,如下所示:

Ticker | TradeDate | ClosePrice | 
----------------------------------------

A1      20201209       1.1       
A1      20201208       1.2
A1      20201207       1.6
.......
A1      20191209       1.1       
A1      20191208       1.2
A1      20191207       1.6

A2      20201209       2.1       
A2      20201208       2.2
A2      20201207       2.6
.......
A2      20191209       2.1       
A2      20191208       2.2
A2      20191207       2.6

現在我想得到這樣的結果(返回的行數與原始表相同):

Ticker | TradeDate | ClosePrice | Past3DaysAverage | Past1MonthAverage | Past1YearAverage

所以前三列與原始表相同。 第四列,我作為參考,表示過去 3 個交易日的平均價格,直到同一股票的 TradeDate(因此partition by )。 到目前為止,我可以編寫如下查詢:

select 
t.Ticker, t.TradeDate, t.ClosePrice, 
avg(t.ClosePrice) over (partition by t.Ticker order by TradeDate rows between 2 preceding and current row) as Past3DaysAverage
from PriceTable t

最后兩列計算同一股票代碼在交易日之前的過去 1 個月和 1 年的平均價格。 現在它很麻煩,因為我不知道如何指定不同的 window 長度(如果可能的話),因為直到不同日期的一年(或一個月)的交易日數不同,所以我不能使用類似的例程ROWS (或RANGE )。 任何人都可以幫助我嗎?

非常感謝!

不幸的是 SQL 服務器不支持 window 函數的range幀。 最簡單的方法可能是橫向連接:

select t.*, t1.*, t2.*, t3.*
from pricetable t
cross apply (
    select avg(t1.closeprice) as past_3days_average
    from pricetable t1
    where 
        t1.ticker = t.ticker 
        and t1.tradedate >= dateadd(day, -3, t.tradedate)
        and t1.tradedate <= t.tradedate
) as t1
cross apply (
    select avg(t1.closeprice) as past_1month_average
    from pricetable t1
    where 
        t1.ticker = t.ticker 
        and t1.tradedate >= dateadd(month, -1, t.tradedate)
        and t1.tradedate <= t.tradedate
) t2
cross apply (
    select avg(t1.closeprice) as past_1year_average
    from pricetable t1
    where 
        t1.ticker = t.ticker 
        and t1.tradedate >= dateadd(year, -1, t.tradedate)
        and t1.tradedate <= t.tradedate
) t3

另一種方法只使用一個橫向連接和條件聚合:

select t.*, t1.*
from pricetable t
cross apply (
    select 
        avg(case when t1.trade_date >= dateadd(day,   -3, t.tradedate) then closeprice end) as past_3days_average,
        avg(case when t1.trade_date >= dateadd(month, -1, t.tradedate) then closeprice end) as past_1month_average,
        avg(t1.closeprice) as past_1year_average
    from pricetable t1
    where 
        t1.ticker = t.ticker 
        and t1.tradedate >= dateadd(year, -1, t.tradedate)
        and t1.tradedate <= t.tradedate
) t1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM