滚动 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
我有一个 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