我有一张股票表,我想为每只股票创建滚动排名。
以下是我的数据集示例:
StockID QuoteID QuoteDay QuoteClose
47 230 2018-04-06 5.1200
47 231 2018-04-07 5.2100
47 232 2018-04-08 5.3000
47 233 2018-04-09 5.2100
47 234 2018-04-10 5.1900
47 235 2018-04-11 5.5200
47 236 2018-04-12 7.1600
47 237 2018-04-13 6.6900
47 238 2018-04-14 6.6300
47 239 2018-04-15 7.0200
47 240 2018-04-16 6.6300
47 241 2018-04-17 6.5800
251 100 2018-04-06 0.1906
251 101 2018-04-07 0.1969
251 102 2018-04-08 0.1986
251 103 2018-04-09 0.2291
251 104 2018-04-10 0.1963
251 105 2018-04-11 0.1995
251 106 2018-04-12 0.2271
251 107 2018-04-13 0.3722
251 108 2018-04-14 0.3073
251 109 2018-04-15 0.3292
251 110 2018-04-16 0.2905
251 111 2018-04-17 0.2784
每天,我想在过去的6天内对QuoteClose进行排名。
例如:
StockID QuoteID QuoteDay QuoteClose 7d Rank
47 230 04/06/18 5.1200
47 231 04/07/18 5.2100
47 232 04/08/18 5.3000
47 233 04/09/18 5.2100
47 234 04/10/18 5.1900
47 235 04/11/18 5.5200
47 236 04/12/18 7.1600 1
47 237 04/13/18 6.6900 2
47 238 04/14/18 6.6300 3
47 239 04/15/18 7.0200 2
47 240 04/16/18 6.6300 4
47 241 04/17/18 6.5800 6
251 100 04/06/18 0.1906
251 101 04/07/18 0.1969
251 102 04/08/18 0.1986
251 103 04/09/18 0.2291
251 104 04/10/18 0.1963
251 105 04/11/18 0.1995
251 106 04/12/18 0.2271 2
251 107 04/13/18 0.3722 1
251 108 04/14/18 0.3073 2
251 109 04/15/18 0.3292 2
251 110 04/16/18 0.2905 4
251 111 04/17/18 0.2784 5
请注意,前6天没有排名。
我在将排名与行号相结合时出现问题,因此我的方法是循环,每次只为7天的数据提供数据。
例如,对于股票#47,在4/12/18,我将比较来自4/6 / 8-4 / 12/8的Quoteclose以确定排名将为1.
然后我将该排名保存到另一个表格。
然后循环将窗口向前移动1天,并找到4/13/18的排名,这将是2.对于该股票,然后对于表格中的所有其他股票重复该过程。
我的计划很复杂,但应该完成工作。
是否有更好,更清晰的方法来实现所有股票的滚动排名?
我正在尝试将此作为一个动态过程,因此我可以生成不同的排名时段:7天,20天等。
答案 0 :(得分:1)
将其分解为步骤:
首先( OrderedRankSets CTE)为每个StockID和QuoteDay获取一组行,其中包括当前行和所有先前行,编号以QuoteDay为单位递减。我们以后可以使用此编号来限制我们将要排名的先前行。
第二个( RankedQuoteDays CTE),对每个报价集中的每一个进行排名,其中我们实际上至少包含每个报价日期间的行数,并且仅包括直到期间长度的行。
最后,我们不需要输出集合的所有行,我们只需要每个报价日的最新值(报价日=前一天的报价日),因此最终查询只会转储(参见{{ 3}})
{{1}}
答案 1 :(得分:0)
我不确定我是否了解您的排名,但我假设它是从最佳(最大数字)到最差(最小)排名的7(可变日)滚动平均值
declare @t table (
StockID int, QuoteID int, QuoteDay date, QuoteClose money)
insert into @t
values
(47,230,'20180406',5.12)
, (47,231,'20180407',5.21)
, (47,232,'20180408',5.3)
, (47,233,'20180409',5.21)
, (47,234,'20180410',5.19)
, (47,235,'20180411',5.52)
, (47,236,'20180412',7.16)
, (47,237,'20180413',6.69)
, (47,238,'20180414',6.63)
, (47,239,'20180415',7.02)
, (47,240,'20180416',6.63)
, (47,241,'20180417',6.58)
, (251,100,'20180406',0.1906)
, (251,101,'20180407',0.1969)
, (251,102,'20180408',0.1986)
, (251,103,'20180409',0.2291)
, (251,104,'20180410',0.1963)
, (251,105,'20180411',0.1995)
, (251,106,'20180412',0.2271)
, (251,107,'20180413',0.3722)
, (251,108,'20180414',0.3073)
, (251,109,'20180415',0.3292)
, (251,110,'20180416',0.2905)
, (251,111,'20180417',0.2784)
declare @dayInRank int = 7
;with cte as
(
select rn=row_number()over(partition by StockID order by QuoteDay)
,*
from @t
)
,RollingAvg as
(
select StockID,QuoteDay,RollingAvg=s.RollingSum/@dayInRank
from cte
cross apply (select SUM(QuoteClose) from cte c2 where cte.StockID=c2.StockID and c2.rn between cte.rn-(@dayInRank-1) and cte.rn) s(RollingSum)
where rn>=@dayInRank
)
select *,Rank=Row_Number()over (partition by StockID order by ra.RollingAvg desc)
from RollingAvg ra
order by StockID,QuoteDay