滚动 52 周高点

Rolling 52 Week High

我有一个 SQL 服务器股票数据库,我正在尝试计算股票的滚动 52 周高点和低点收盘价。

当使用 window 函数 MAX() 并尝试分区到滚动的 52 周时间段时,我如何才能将分区限制为仅滚动的 52 周(或 1 年时间段)?

我相信我正在做的事情(截图)将产生 365 滚动观察的滚动最大值。但由于市场在周末和节假日休市,这实际上可能与 52 周不同:

SELECT 
symbol, 
dates, 
[close],

MAX( [close] ) OVER(PARTITION BY symbol 
    ORDER BY dates
    ROWS BETWEEN 364 PRECEDING AND CURRENT ROW) AS [52_week_high]

FROM dbo.adj_daily_prices

WHERE 
dates BETWEEN CAST('2019-01-01' AS DATE) AND CAST('2021-10-15' AS DATE)
AND
symbol = 'CLR'
AND
is_last = 1

ORDER BY
dates DESC

我想有一个聪明的方法可以用 CASE WHEN 表达式来做到这一点?

您所描述的目前在 Microsoft SQL Server 中的分析功能是不可能的,但在其他数据库中是可能的。参见 https://modern-sql.com/caniuse/over_range_between_(datetime)

您也可以使用与日期条件相同的 table 的联接:

select    p.symbol, 
          p.dates, 
          p.[close],
          max(h.[close]) as [52_week_high],
          min(h.[close]) as [52_week_low]
from      adj_daily_prices  p
     join adj_daily_prices  h
       on p.symbol = h.symbol
      and h.dates between dateadd(year,-1,p.dates) and p.dates
where     p.dates between '2019-01-01' and '2021-10-15'
      and p.symbol = 'CLR'
group by  p.symbol, 
          p.dates, 
          p.[close]
order by  p.dates desc;

'main query' 我指的是返回结果的最后一步。但无论如何,我现在明白你不希望解决方案被限制在 1 年内,所以,我相信这个更接近你所寻求的。没有 CTE 或日历表,只是作为 select 列表达式的子查询。不限年。

(我不知道你的 is_last 专栏是做什么的,所以我只是包括了 is_last=1 认为它可能标志着最近的每个符号和日期的行)


with
adj_daily_prices as ( -- this simulates your table
    select *
    from (values
          ('CLR', '2021-01-01', 58, 1)
        , ('CLR', '2019-04-05', 70, 1)
        , ('CLR', '2021-01-05', 56, 1)
        , ('CLR', '2021-02-15', 60, 1)
        ) T(symbol, dates, [close], is_last)
)
SELECT 
    symbol, 
    dates, 
    [close],
    (select max([close])
     from adj_daily_prices ftWkh
     where ftWkh.symbol=adp.symbol
     and is_last=1
     and ftWkh.dates between dateadd(week, -52, adp.dates) and adp.dates
     )  AS [52_week_high]
FROM 
    adj_daily_prices adp

WHERE 
    adp.dates BETWEEN CAST('2019-01-01' AS DATE) AND CAST('2021-10-15' AS DATE)
    AND
    symbol = 'CLR'
    AND
    is_last = 1
ORDER BY
adp.dates desc