我可以使用递归cte来扩展分区吗?

时间:2012-05-13 20:59:30

标签: sql-server sql-server-2008-r2

我正在研究一个我认为需要递归的查询。在这种情况下,我无法弄清楚基本情况以及如何构建它。我有股票市场数据,我想比较按日期排序的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

1 个答案:

答案 0 :(得分:3)

如果我没有遗漏任何东西,这可以在没有递归CTE的情况下解决。

这个想法如下:

  1. (Symbol, FastPeriod, SlowPeriod)的降序排列TradeDate的每个分区中的行(我猜)。

  2. (Symbol, FastPeriod, SlowPeriod, ChgSign)的everty分区中的行进行排名(同样,按TradeDate的降序排列。)

  3. 找出两个排名之间的差异。这将是最终分区的附加标准。

  4. 现在,您可以再次对行进行排名,按(Symbol, FastPeriod, SlowPeriod, ChgSign, RankDiff)对其进行分区。

  5. 以下是生成的查询的外观:

    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