2011-12-14 11 views
0

私は、結果セットあなたはそれぞれが過ごす見ることができるようにT-SQL分割行?

Rank cardID  DespatchValue Spend SumSpend Spendtype 
0  468612  500    0   0   Despatch 
1  468612  500    -8500  -8500  Topup 
2  468612  500   -11500  -20000  Topup 
3  468612  500    -3500  -23500  Topup 

の下には、私は幸せです(再帰CTEを経由して)合計支出に追加されています。

ロジックは、その後型バランス

  • 何か=だから、トップアップ
  • を過ごし=過ごす初期することが

    • デスパッチ値を作業する必要がしかし、

      私は考え見ることを好む:

      Rank cardID DespatchValue Spend SumSpend Spendtype 
      0  468612 500    0  0  Despatch 
      ?  468612 500    -500 -500  Balance 
      1  468612 500    -8000 -8500  Topup 
      2  468612 500    -11500 -20000  Topup 
      3  468612 500    -3500 -23500  Topup 
      

      これを達成するためのアイデアはありますか?

    +0

    私は行く方法のビットで少しです。 googleのビュー "分割行"の検索ページを読むが、それらはすべて私が必要なもののために少し強く見える。自己参加について考えていますが、どこから始めるべきかは不明です –

    答えて

    1

    分割行を実行するには、2つ以上のUNION句をCTEに追加する必要があります。ほとんどの再帰的なCTEには、「アンカー」と再帰的なビットがあります。その再帰的ビットがどのように機能するかを拡張する必要があります。まず、「名目上の」ケースをいつ押し詰めるかを特定します。これは、バランスが正の合計から負の値に移行するときです。あなたの場合、それは "DespatchValue + SumSpend"です。

    次の2つの用語は、あなたの「分割」行になります。上記のいずれかの条件の逆を使用して(つまり、この「特別な」条件で行を戻すだけで)最初のUNIONは "BALANCE"レコードになり、0になります。2番目のUNIONは残りの部分の残りの部分です。

    ここで私が思いついたのは、「残高」を示すために(そして、後で再帰する際に重複を防ぐために)「subid」列を追加したことに注意してください。私はまた、「DespatchBalance」を追加しました。それはあなたがチェックしているものであると仮定します。具体的なものを除いて、一般的なフォーマットは良いはずです:

    declare @txn as table (
        id int, 
        cardID int, 
        DespatchValue int, 
        Spend int 
        --SumSpend int, 
        --Spendtype varchar(50) 
    ) 
    
    insert into @txn 
            select 0, 468612, 500, 0--, 0, 'Despatch' 
    union all select 1, 468612, 500, -8500--, -8500, 'Despatch' 
    union all select 2, 468612, 500, -11500--, -20000, 'Despatch' 
    union all select 3, 468612, 500, -3500--, -23500, 'Despatch' 
    
    
    ;with x (id, subid, cardID, DespatchValue, Spend, SumSpend, DespatchBalance, Despatch) as 
    (
        --Anchor - beginning record 
        select id, 0, cardID, DespatchValue, Spend 
        , Spend as SumSpend 
        , DespatchValue as DespatchBalance 
        , 'Despatch' as Despatch 
        from @txn 
        where id = 0 
    
        UNION ALL  
        -- primary CTE - identify all nominal 'Topup' records 
        select t.id, 0, t.cardID, t.DespatchValue, t.Spend 
        , x.SumSpend + t.Spend 
        , x.DespatchBalance + t.Spend 
        , 'Topup' 
        from @txn t 
        join x 
         on x.id + 1 = t.id 
         and x.subid = 0 
        where x.DespatchBalance <= 0 
    
        UNION ALL 
    
        -- These two UNIONs do a split record: 
    
        -- First half of split - the remaining amount to a balance of 0 
        select t.id, 1 -- special "subid" to indicate it's a split record 
        , t.cardID, t.DespatchValue 
        , - x.DespatchBalance 
        , x.SumSpend - x.DespatchValue -- only capture the remaing bit above balance 
        , 0 -- DespatchBalance should be 0 
        , 'Balanace' 
        from @txn t 
        join x 
         on x.id + 1 = t.id 
         and x.subid = 0 
        where x.DespatchBalance > 0 
         and x.DespatchBalance + t.Spend < 0 
    
        UNION ALL 
        -- Second half of split - record that this is an overflow after "Balance" reached 
        select t.id, 0 
        , t.cardID, t.DespatchValue 
        , t.Spend + x.DespatchBalance 
        , x.SumSpend + t.Spend 
        , x.DespatchBalance + t.Spend 
        , 'Topup' 
        from @txn t 
        join x 
         on x.id + 1 = t.id 
         and x.subid = 0 
        where x.DespatchBalance > 0 
         and x.DespatchBalance + t.Spend < 0 
    ) 
    
    select * 
    from x 
    option (MAXRECURSION 100)