我正在研究一个我认为需要递归的查询。在这种情况下,我无法弄清楚基本情况以及如何构建它。我有股票市场数据,我想比较按日期排序的desc的移动平均线,以及两个移动平均线之间的差异符号(以及按照cte的符号和周期值)的行数/分区。我使用0和1的列来帮助确定分区。对于标准分区,如果一组行的值为0,则结果切换为1然后返回0,0将全部分区在一起。我在结果集中需要的是每个从0到1的变化的新分区,反之亦然。我添加了代码,因为我现在拥有它(不会返回第二列,这是为了显示我想要的输出而添加的)以及我到目前为止的一些示例数据,再次使用第二列(RowNInner)作为我正在尝试的列实现:
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
样本结果集(我想要的第二列):
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
答案 0 :(得分:3)
如果我没有遗漏任何东西,这可以在没有递归CTE的情况下解决。
这个想法如下:
按(Symbol, FastPeriod, SlowPeriod)
的降序排列TradeDate
的每个分区中的行(我猜)。
对(Symbol, FastPeriod, SlowPeriod, ChgSign)
的everty分区中的行进行排名(同样,按TradeDate
的降序排列。)
找出两个排名之间的差异。这将是最终分区的附加标准。
现在,您可以再次对行进行排名,按(Symbol, FastPeriod, SlowPeriod, ChgSign, RankDiff)
对其进行分区。
以下是生成的查询的外观:
WITH allData AS
(
SELECT
t1.Symbol,
TradeDate = t.TradingDate,
FastPeriod = t1.Period,
SlowPeriod = t2.Period,
FastValue = t1.Value,
SlowValue = t2.Value,
SlowFastDiff = (t1.Value - t2.Value),
ChgSign = CASE WHEN t1.Value < t2.Value THEN 0 ELSE 1 END
FROM tblTradingDays t
RIGHT JOIN tblDailySMA t1 ON t.TradingDate = t1.TradeDate
INNER JOIN tblDailySMA t2 ON t1.Symbol = t2.Symbol
AND t1.TradeDate = t2.TradeDate
WHERE t1.Period < t2.Period
AND t1.Symbol < 'AC'
)
, partitioned AS (
SELECT
RowOuter = DENSE_RANK() OVER (ORDER BY Symbol, FastPeriod, SlowPeriod),
RankDiff = ROW_NUMBER() OVER (
PARTITION BY Symbol, FastPeriod, SlowPeriod
ORDER BY TradeDate DESC
)
- ROW_NUMBER() OVER (
PARTITION BY Symbol, FastPeriod, SlowPeriod, ChgSign
ORDER BY TradeDate DESC
),
Symbol,
TradeDate,
FastPeriod,
SlowPeriod,
FastValue,
SlowValue,
SlowFastDiff,
ChgSign
FROM allData
)
SELECT
RowOuter,
RowInner = ROW_NUMBER() OVER (
PARTITION BY Symbol, FastPeriod, SlowPeriod, ChgSign, RankDiff
ORDER BY TradeDate DESC
),
Symbol,
TradeDate,
FastPeriod,
SlowPeriod,
FastValue,
SlowValue,
SlowFastDiff,
ChgSign
FROM partitioned
ORDER BY Symbol, FastPeriod, SlowPeriod, TradeDate DESC, RowNInner