2017-02-05 4 views
0

の別の一つの行の一部の列を更新する私はこのようになりますいくつかのデータを持っている:http://sqlfiddle.com/#!6/21a06/1は同じテーブル

id step valA valB valC 
------------------------------ 
100 1  NULL 2  3 
101 2  4  5  6 
102 3  7  NULL 9 
103 3  10  11  12 
104 4  13  14  15 
105 4  NULL 14  15 
106 5  NULL 18  19 
107 5  20  18  19 

idが一意のフィールドです。私は、次の行の特定の列(この例ではvalAとvalB)から特定の行の値を更新するクエリを考え出しています。両方の行の 'step'が一致する場合(2つ以上の行が一致することは決してありません)、valAまたはvalBのいずれかの値が最初の行で(listidの値が小さい)NULLであれば、次の行の列が最初の行にコピーされます。

したがって、上記の表の例では、id = 102の行は、valBを11に更新する必要があります(ID = 103の次の行のvalBと一致させるため)。また、id = 106の行は、valAを20に更新する必要があります(ID = 107の次の行のvalAに一致させるため)。指定された行のペアは、同時にvalAとvalBの両方で条件を満たす(両方ともNULL)場合があります。 step = 1の他の行がないためid = 100の行は影響を受けず、NULLは「ステップ」のペアの2番目の行にあるため、id = 105の行もタッチされません。

結果は次のようになります。それは容易になる場合

id step valA valB valC 
------------------------------ 
100 1  NULL 2  3 
101 2  4  5  6 
102 3  7  11  9 
103 3  10  11  12 
104 4  13  14  15 
105 4  NULL 14  15 
106 5  20  18  19 
107 5  20  18  19 

、ID = 105の行にNULLはまた、ID = 104の行(13)からの値に更新することができ、それはありません必要。

私は関連すると思われるいくつかの質問を見つけました。内側の結合などでさまざまなことを試みましたが、効果があったものを思い付くことができませんでした。これは私の基本的なSQLの経験を超えています。どんな助けもありがとうございます。

答えて

0

ROW_NUMBERを使用すると、一致するペアの最初の行を取得できます。次に、APPLYを使用して、2番目のペアから代替値を取得します。

WITH CTE AS(
    SELECT *, 
     Rn = ROW_NUMBER() OVER(PARTITION BY step ORDER BY id) 
    FROM TestTable 
) 
SELECT 
    c.id, 
    c.step, 
    valA = ISNULL(c.valA, x.valA), 
    valB = ISNULL(c.valB, x.valB), 
    c.valC 
FROM CTE c 
OUTER APPLY(
    SELECT TOP(1) * 
    FROM TestTable t 
    WHERE 
     t.id > c.id 
     AND t.step = c.step 
    ORDER BY t.id 
) x 
WHERE 
    Rn = 1 
    OR (c.valA IS NULL OR c.valB IS NULL) 

UNION ALL 

SELECT 
    id, step, valA, valB, valC 
FROM CTE 
WHERE 
    Rn = 2 
    AND valA IS NOT NULL 
    AND valB IS NOT NULL 
ORDER BY Id; 

ONLINE DEMO

+0

ありがとう!私はそれがより良い方法を理解するためにそれを通過しているが、それは私が必要なものを行うだろうように見えます。しかし、元のテーブルではなくcに変更が加えられたようです。例えば。私がTestTableからselect *を続けると、元のデータが得られます。元のテーブル行が変更されるようにこれを行うことは可能ですか? – AngeloQ

関連する問題