问题
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