2012-02-17 2 views
1

Iは、以下の構造を持つテーブルを継承:残り(rn <>1)が挿入(順次)更新する必要がありながらCTEをパスの更新に使用できますか?

rowID rn userID Data1 Data2 Data3 
----- -- ------ ----- ---- ---- 
1  1 1  A  null 123 
2  2 1  B  111 null 
3  1 2  C  222 333 
4  2 2  D  null null 
5  3 2  E  111 null 
6  1 3  F  333 222 

第RECS(rn=1)は、挿入される必要があります。 where rn = 1を使用して簡単に挿入し、userIDがないかどうかを確認できます。

私の問題は、私は、ユーザー表が最新の状態が反映されるようになりましたrn <>1を使用して順次、すべてのRECSを更新する必要があるということです。それ、更新後のユーザテーブルには、次のようになり、次のとおりです。

rowID userID Data1 Data2 Data3 
----- ------ ----- ----- ----- 
1  1  B  111 123 
2  2  E  111 333 
3  3  F  333 222 

私の考えはそれぞれ「合格」のすべてのRECSをつかむだろうCTEを、書くことがあった場所RN = 2、そして= RN 3、その後、RN = 4 ....私はもう処理する必要がありません。この方法で、私はセットで更新することができます。

が、これは可能です(または私がやる-しばらく使用する必要がありますか)?もしそうなら、再帰的なものか「通常の」CTEが必要ですか?

;with my_cte (rowID, rn, userID, Data1, Data2, Data3, val) As 
(
    SELECT rowID, rn, userID, Data1, Data2, Data3, val 
    from @MyTempTable x 
    where rn =1 

     UNION ALL 

    SELECT rowID, rn, userID, Data1, Data2, Data3, b.val +1 
    from @MyTempTable y 
    INNER JOIN 
     my_cte b 
    ON y.userID = b.userID 
    WHERE y.rn = b.val +1 

) 
UPDATE userTable 
SET 
    [Data1] = COALESCE(c.Data1, [Data1]) 
    ,[Data2]= COALESCE(c.Data2, [Data2]) 
    ,[Data3]= COALESCE(c.Data3, [Data3]) 
From @MyTempTable c 
JOIN 
    ( SELECT user_id 
     FROM my_cte 
     WHERE rn<>1 
    ) b 
ON b.user_id = c.user_id 
WHERE 
    EXISTS 
     ( Select userID 
      from userTable q 
      Where q.userId = b.userId 
     ) 

が、私はこれを動作させることができなかった、それは最初の行だけが更新されるようになっています。ここでは

は、私が試したものです。何かご意見は?私はCTEのつもりです。何よりも、CTEが何をしているのかを知りたがっています...アップデートが「パス」で実行される可能性はありますか?

+0

'Data1'がために' userID' 1は**すべきではない** Bとあなたの現在の最大値は何ですか'rn'? –

+0

@リーブン、そうです。私は元の投稿を編集しました。私は何ができるか分からない。それは現在最大19で、私は確かに高くなる可能性があります。 – user991945

答えて

1

CTE後、あなたの与えられた入力のためのあなたの特定の出力を返します。これらの結果を、レコードを別のテーブルに挿入するための開始点として使用できます。

それの要旨は

  • あるrn=1すべての行で始まる、再帰CTEを使用してください。再帰部分で
  • 、可能な場合は再帰部分からData1-3を選択し、そうでなければexisiting値(COALESCE)を保持します。 CTEの結果は、今、あなたの最終的な値+ rn=1
  • は、既存のrn上の各userIDについてROW_NUMBERが、ORDER DESCを追加します。初期値です。これは最新値は最後にROWNUMBER 1とすべてを選択して、最終結果ごとに別のROWNUMBERを追加1.
  • ROWNUMBER得ることを確認します。

SQLステートメント

;WITH q AS (
    SELECT rn 
      , UserID 
      , Data1 
      , Data2 
      , Data3 
    FROM Inherited 
    WHERE rn = 1 
    UNION ALL 
    SELECT i.rn 
      , i.UserID 
      , COALESCE(i.Data1, q.Data1) 
      , COALESCE(i.Data2, q.Data2) 
      , COALESCE(i.Data3, q.Data3) 
    FROM q 
      INNER JOIN Inherited i ON i.rn = q.rn+1 AND i.userID = q.userID 
) 
SELECT rn = ROW_NUMBER() OVER (ORDER BY userID) 
     , * 
FROM (
      SELECT UserID 
        , Data1 
        , Data2 
        , Data3 
        , rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY rn DESC) 
      FROM q 

     ) t 
WHERE rn = 1       

テストスクリプト

;WITH Inherited (rowID, rn, userID, Data1, Data2, Data3) AS (
    SELECT * FROM (VALUES 
    (1, 1, 1, 'A', null, '123') 
    , (2, 2, 1, 'B', '111', null) 
    , (3, 1, 2, 'C', '222', '333') 
    , (4, 2, 2, 'D', null, null) 
    , (5, 3, 2, 'E', '111', null) 
    , (6, 1, 3, 'F', '333', '222') 
) a (b, c, d, e, f, g) 
) 
, q AS (
    SELECT rn 
      , UserID 
      , Data1 
      , Data2 
      , Data3 
    FROM Inherited 
    WHERE rn = 1 
    UNION ALL 
    SELECT i.rn 
      , i.UserID 
      , COALESCE(i.Data1, q.Data1) 
      , COALESCE(i.Data2, q.Data2) 
      , COALESCE(i.Data3, q.Data3) 
    FROM q 
      INNER JOIN Inherited i ON i.rn = q.rn+1 AND i.userID = q.userID 
) 
SELECT rn = ROW_NUMBER() OVER (ORDER BY userID) 
     , * 
FROM (
      SELECT UserID 
        , Data1 
        , Data2 
        , Data3 
        , rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY rn DESC) 
      FROM q 

     ) t 
WHERE rn = 1       
+0

非常にクールで、動作します。私も理解していると思う:最初のパスで、あなたはアンカー(rn = 1)を持っています。それから、自身とのUNIONSとNEXTレコード(rn + 1)のJOINS自体。これにより、データを結合することができます。私たちはrn + 1条件が失敗するまで続けます。これにより、一連の連続的に合体した行が与えられ、最新の行を持つユーザー表が出力されます。私はそれを持っていますか? (私は途中でこれが大好き!) – user991945

+0

@ user991945 - あなたはそれ以上に説明しました。 –

関連する問題