SQL Server recursive cte help wanted

ⅰ亾dé卋堺 提交于 2019-12-11 12:29:04

问题


I'm trying to generate a data set, and I think recursion is required, but I can't quite adapt the numerous examples I've found to my purposes. The end result I want is fairly simple to describe.

Two tables are involved: the first with trading pricing for stocks with the relevant fields TradeDate, Symbol, and Clse (closing price), and a table with trading days listed. I'd like to partition the pricing data by symbol, ordered by date, but I'd like the partition/ row numbering to break if a trade date is missing from the pricing table, since this data comes in from a web service that is a little unpredictable at times.

My first attempt was a simple enough select query that had a WHERE clause that called a udf I wrote to see if there was continuous data for that symbol/ date combination. It worked (it ran) and the night I ran it, after 7 hours it was almost through the symbols starting with 'A.'

EDIT:
This post of mine and the response a little while back SQL server select query help for stored procedure needed on SO was helpful conceptually, but my current use of the concept requires a little more (table join, partitioning/ row numbering etc)

If it helps understand the problem, I want to use what's returned to calculate various aggregations per symbol, trade date combination that use the past data points. Example: 5 period moving average of closing price for a symbol/ trade date would be the average of the five closing prices (clse) that have a trade date <= the date being calculated for. So using the sample data below from the first table, I want to return 9.02 for symbol 'A', 3 periods, trade date 1/3/12. If data is missing for one of the calculations I want null.

This result set I want would be a simple PARTITION select query if it weren't for having to check for missing dates. So here is some sample data of the tables involved and my goal result set:

tblDailyPricingAndVol

TradeDate Symbol Clse
1/1/12    A      9.01
1/2/12    A      9.05
1/3/12    A      8.99
1/5/12    A      9.03
1/1/12    B      10.05
1/4/12    B      10.11
1/5/12    B      10.03

tblTradingDays

TradingDate
1/1/12
1/2/12
1/3/12
1/4/12
1/5/12

Goal result set:

RowNumber TradeDate Symbol Clse
1         1/1/12    A      9.01
2         1/2/12    A      9.05
3         1/3/12    A      8.99
1         1/5/12    A      9.03
1         1/1/12    B      10.05
1         1/4/12    B      10.11
2         1/5/12    B      10.03

Hope that makes sense. Any help would be appreciated. I think I'll see recursive cte's much more clearly if I can get one running as expected on my own data. Thanks.


回答1:


I think combining dense_rank() and row_number() will work here:

; with cte as (
    select d.TradingDate,p.Symbol,p.Clse
    , r=DENSE_RANK()over(order by d.TradingDate)
    , r1=row_number()over(partition by p.Symbol order by p.TradeDate)
    from tblTradingDays d
    inner join tblDailyPricingAndVol p on d.TradingDate=p.TradeDate
)
select
RowNumber=row_number()over(partition by Symbol, (r-r1) order by TradingDate)
, TradingDate,Symbol,Clse
from cte
go

Result:




回答2:


set dateformat mdy

declare @tblDailyPricingAndVol table
(
  TradeDate date,
  Symbol char(1),
  Clse money
)

insert into @tblDailyPricingAndVol values
('1/1/12',    'A',      9.01),
('1/2/12',    'A',      9.05),
('1/3/12',    'A',      8.99),
('1/5/12',    'A',      9.03),
('1/1/12',    'B',      10.05),
('1/4/12',    'B',      10.11),
('1/5/12',    'B',      10.03)

;with C as
(
  select TradeDate,
         Symbol,
         Clse,
         row_number() over(partition by Symbol order by TradeDate) as rn
  from @tblDailyPricingAndVol
)
select row_number() over(partition by Symbol, datediff(day, 0, TradeDate) - rn 
                         order by TradeDate) as RowNumber,
       TradeDate,
       Symbol,
       Clse
from C
order by Symbol, TradeDate


来源:https://stackoverflow.com/questions/9555354/sql-server-recursive-cte-help-wanted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!