2016-11-30 4 views
2
に参加

コード:T-SQLは、NULLとNOT NULLレコード

CREATE TABLE [dbo].[T1] ([ID1] INT NOT NULL, [ID2] INT NOT NULL); 
CREATE TABLE [dbo].[T2] ([ID1] INT NOT NULL, [ID2] INT NULL, [VAL] INT NOT NULL); 

INSERT INTO [dbo].[T1] ([ID1], [ID2]) 
VALUES (1, 1) 
     ,(1, 2) 
     ,(1, 3) 
     ,(1, 4) 
     ,(1, 5) 
     ,(2, 1); 

INSERT INTO [dbo].[T2] ([ID1], [ID2], [VAL]) 
VALUES (1, NULL, 25000) 
     ,(1, 2, 30000) 
     ,(2, NULL, 30000); 

目標:

T1は、ID1とID2マッピングの完全なリストを持っています。
T2は、ValにマップされたID1/ID2を持つ外部テーブルです。

最終的な目標は、T2.ID2 = NULLのときにT1とT2(ID1/ID2)を「クロス結合」することですが、T2.ID2がNOT NULL値を持つときにそのT1.ID2の出力をスキップし、 T2はNOT-NULL T2.ID2sになります。パフォーマンスは速くなければならない!

所望の出力:

ID1 ID2 VAL 
1 1 25000 
1 2 30000 -- T1.ID2 = 2 takes the priority 
1 3 25000 
1 4 25000 
1 5 25000 
2 1 30000 

マイ試してみてください。

SELECT [T2].[ID1] 
     , [T1].[ID2] 
     , [T2].[VAL] 
FROM [dbo].[T1] [T1] 
JOIN [dbo].[T2] [T2] 
ON  [T1].[ID1] = [T2].[ID1] 
WHERE [T2].[ID2] IS NULL 
     OR [T1].[ID2] IN (SELECT [T3].[ID2] 
          FROM  [dbo].[T2] [T3] 
          WHERE  [T2].[ID1] = [T3].[ID1] 
            AND [T2].[ID2] = [T3].[ID2]) 
--ORDER BY [T2].[ID1] 
--  , [T1].[ID2] 
--  , [T2].[VAL]; 

電流出力:

ID1 ID2 VAL 
1 1 25000 
1 2 25000 
1 3 25000 
1 4 25000 
1 5 25000 
1 2 30000 
2 1 30000 

DROP TABLE [dbo].[T1]; 
DROP TABLE [dbo].[T2]; 

答えて

2

あなたのルックアップテーブルのデフォルト値を持っています。あなたがこのleft joincoalesce()を使用して近づくことができる:あなたが参加する中で使用されるID列の右のインデックスを持っていると仮定すると

select t1.id1, t1.id2, 
     coalesce(t2.val, t2default.val) as val 
from t1 left join 
    t2 
    on t1.id1 = t2.id1 and t1.id2 = t2.id2 left join 
    t2 t2default 
    on t1.id1 = t2default.id1 and t2default.id2 is null; 

を、パフォーマンスが非常に良いことがあります。

あなたはパフォーマンスを気にした場合、別の方法は試してみる価値があるかもしれない:

select t1.id1, t1.id2, t2.val 
from t1 outer apply 
    (select top 1 t2.* 
     from t2 
     where t2.id1 = t1.id and (t2.id2 is null or t2.id2 = t1.id2) 
     order by (case when t2.id2 = t1.id2 then 1 else 2 end) 
    ) t2; 

これは私にはもっと複雑なようだが、時にはapplyは驚くほど良好な性能特性を持っています。

+0

ありがとうございましたGordon、期待どおりに動作します。興味深いことに、軽微な見落としでない限り、最初のクエリでID2を結合しなかったのはなぜですか(つまり、coalesce(t2.id2、t1.id2)をid2)? Btwは、驚くべきことに、最初のソリューションは上記のデータの2番目のソリューションより優れたエグゼクティブプランを提供しました。実際の/より大きなテーブルでロジックを試して比較します。再度、感謝します。 – 007

+0

@ 007。 。 。それはタイプミスでした。 't1.id2'でなければなりません。 –

関連する問題