I’m working on a query that I think I need recursion for. In this case, I can’t quite figure out the base case and how to structure it. I have stock market data, and I want to compare moving averages ordered desc by date, and row number/ partition by the sign of the difference between two moving averages (as well as on symbol and period values as per cte). I’m using a column of 0 and 1 to help determine the partitions. With a standard partition, if a group of rows has a value of 0, then the results switch to 1 then back to 0, the 0’s are all partitioned together. what I need in my result set is a new partition for each change from 0 to 1 or vice versa. I added the code as I have it now (doesn’t return 2nd column, that’s added to show my desired output) and some sample data I have thus far below, again with the 2nd column (RowNInner) being the column I’m trying to achieve:
WITH allData AS
(
SELECT t1.Symbol, t.TradingDate AS TradeDate, t1.Period AS FastPeriod, t2.Period AS SlowPeriod,
t1.Value AS FastValue, t2.Value AS SlowValue, (t1.Value - t2.Value) AS SlowFastDiff,
CASE
WHEN (t1.Value - t2.Value) < 0 THEN 0
ELSE 1
END AS ChgSign
FROM tblTradingDays t RIGHT JOIN tblDailySMA t1 ON t.TradingDate = t1.TradeDate JOIN tblDailySMA t2 ON
t1.Symbol = t2.Symbol AND t1.TradeDate = t2.TradeDate
WHERE t1.Period < t2.Period AND t1.Symbol < 'AC'
)
SELECT DENSE_RANK() OVER (ORDER BY Symbol, FastPeriod,
SlowPeriod) AS RowNOuter, Symbol, TradeDate, FastPeriod, SlowPeriod, FastValue, SlowValue,
SlowFastDiff, ChgSign
FROM allData
ORDER BY Symbol, FastPeriod, SlowPeriod, TradeDate DESC, RowNInner
Sample result set (2nd column is what I seek):
RowNOuter RowNInner Symbol TradeDate FastPeriod SlowPeriod FastValue SlowValue SlowFastDiff ChgSign
1 1 A 5/11/2012 5 10 40.05 41.166 -1.116 0
1 2 A 5/10/2012 5 10 40.362 41.477 -1.115 0
1 3 A 5/9/2012 5 10 40.856 41.702 -0.846 0
1 1 A 5/8/2012 5 10 42.018 41.78 0.238 1
1 2 A 5/7/2012 5 10 42.282 41.821 0.461 1
1 1 A 5/6/2012 5 10 41.542 41.797 -0.255 0
1 2 A 5/5/2012 5 10 41.36 41.778 -0.418 0
If I am not missing anything, this can be solved without a recursive CTE.
The idea is as follows:
Rank the rows within every partition of
(Symbol, FastPeriod, SlowPeriod)in the descending order ofTradeDate(I guess).Rank the rows within everty partition of
(Symbol, FastPeriod, SlowPeriod, ChgSign)(again, in the descending order ofTradeDate).Find the difference between the two rankings. This will be an additional criterion for the final partitioning.
Now you can just rank the rows once again, partitioning them by
(Symbol, FastPeriod, SlowPeriod, ChgSign, RankDiff).Here’s what the resulting query might look like: